feat(karmada-search): Implement SearchRegistry reconcile logic
Co-authored-by: liys87x <liyasong1987x@gmail.com> Signed-off-by: huntsman_ly <huntsman_ly@sina.com>
This commit is contained in:
parent
58c0bc4887
commit
de186ea043
|
@ -90,6 +90,16 @@ func (o *Options) Run(ctx context.Context) error {
|
|||
return nil
|
||||
})
|
||||
|
||||
server.GenericAPIServer.AddPostStartHookOrDie("start-karmada-search-controller", func(context genericapiserver.PostStartHookContext) error {
|
||||
// start ResourceRegistry controller
|
||||
ctl, err := search.NewController(restConfig, search.CachedResourceHandler())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
ctl.Start(context.StopCh)
|
||||
return nil
|
||||
})
|
||||
|
||||
return server.GenericAPIServer.PrepareRun().Run(ctx.Done())
|
||||
}
|
||||
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
package search
|
||||
|
||||
import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
|
||||
)
|
||||
|
||||
// +genclient
|
||||
|
@ -24,9 +25,9 @@ type ResourceRegistry struct {
|
|||
|
||||
// ResourceRegistrySpec defines the desired state of ResourceRegistry.
|
||||
type ResourceRegistrySpec struct {
|
||||
// ClusterSelectors represents the filter to select clusters.
|
||||
// TargetCluster is the cluster that the resource registry is targeting.
|
||||
// +required
|
||||
ClusterSelectors []ClusterSelector
|
||||
TargetCluster *policyv1alpha1.ClusterAffinity `json:"targetCluster"`
|
||||
|
||||
// ResourceSelectors used to select resources.
|
||||
// +required
|
||||
|
@ -38,42 +39,15 @@ type ResourceRegistrySpec struct {
|
|||
StatusUpdatePeriodSeconds uint32
|
||||
}
|
||||
|
||||
// ClusterSelector represents the filter to select clusters.
|
||||
type ClusterSelector struct {
|
||||
// LabelSelector is a filter to select member clusters by labels.
|
||||
// If non-nil and non-empty, only the clusters match this filter will be selected.
|
||||
// +optional
|
||||
LabelSelector *metav1.LabelSelector
|
||||
|
||||
// FieldSelector is a filter to select member clusters by fields.
|
||||
// If non-nil and non-empty, only the clusters match this filter will be selected.
|
||||
// +optional
|
||||
FieldSelector *FieldSelector
|
||||
|
||||
// ClusterNames is the list of clusters to be selected.
|
||||
// +optional
|
||||
ClusterNames []string
|
||||
|
||||
// ExcludedClusters is the list of clusters to be ignored.
|
||||
// +optional
|
||||
ExcludeClusters []string
|
||||
}
|
||||
|
||||
// FieldSelector is a field filter.
|
||||
type FieldSelector struct {
|
||||
// A list of field selector requirements.
|
||||
MatchExpressions []corev1.NodeSelectorRequirement
|
||||
}
|
||||
|
||||
// ResourceSelector the resources will be selected.
|
||||
type ResourceSelector struct {
|
||||
// APIVersion represents the API version of the target resources.
|
||||
// +required
|
||||
APIVersion string
|
||||
|
||||
// Kind represents the Kind of the target resources.
|
||||
// Kind represents the kind of the target resources.
|
||||
// +required
|
||||
Kind string
|
||||
Kind string `json:"kind"`
|
||||
|
||||
// Namespace of the target resource.
|
||||
// Default is empty, which means all namespaces.
|
||||
|
|
|
@ -1,17 +1,18 @@
|
|||
package v1alpha1
|
||||
|
||||
import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
|
||||
)
|
||||
|
||||
const (
|
||||
// ResourceKindResourceRegistry is the name of the resource registry
|
||||
ResourceKindResourceRegistry = "ResourceRegistry"
|
||||
// ResourceSingularResourceRegistry is singular name of ResourceRegistry.
|
||||
ResourceSingularResourceRegistry = "resourceRegistry"
|
||||
ResourceSingularResourceRegistry = "resourceregistry"
|
||||
// ResourcePluralResourceRegistry is plural name of ResourceRegistry.
|
||||
ResourcePluralResourceRegistry = "resourceRegistries"
|
||||
ResourcePluralResourceRegistry = "resourceregistries"
|
||||
// ResourceNamespaceScopedResourceRegistry is the scope of the ResourceRegistry
|
||||
ResourceNamespaceScopedResourceRegistry = false
|
||||
)
|
||||
|
@ -35,9 +36,9 @@ type ResourceRegistry struct {
|
|||
|
||||
// ResourceRegistrySpec defines the desired state of ResourceRegistry.
|
||||
type ResourceRegistrySpec struct {
|
||||
// ClusterSelectors represents the filter to select clusters.
|
||||
// TargetCluster is the cluster that the resource registry is targeting.
|
||||
// +required
|
||||
ClusterSelectors []ClusterSelector `json:"clusterSelectors"`
|
||||
TargetCluster *policyv1alpha1.ClusterAffinity `json:"targetCluster"`
|
||||
|
||||
// ResourceSelectors used to select resources.
|
||||
// +required
|
||||
|
@ -49,40 +50,13 @@ type ResourceRegistrySpec struct {
|
|||
StatusUpdatePeriodSeconds uint32 `json:"statusUpdatePeriodSeconds,omitempty"`
|
||||
}
|
||||
|
||||
// ClusterSelector represents the filter to select clusters.
|
||||
type ClusterSelector struct {
|
||||
// LabelSelector is a filter to select member clusters by labels.
|
||||
// If non-nil and non-empty, only the clusters match this filter will be selected.
|
||||
// +optional
|
||||
LabelSelector *metav1.LabelSelector `json:"labelSelector,omitempty"`
|
||||
|
||||
// FieldSelector is a filter to select member clusters by fields.
|
||||
// If non-nil and non-empty, only the clusters match this filter will be selected.
|
||||
// +optional
|
||||
FieldSelector *FieldSelector `json:"fieldSelector,omitempty"`
|
||||
|
||||
// ClusterNames is the list of clusters to be selected.
|
||||
// +optional
|
||||
ClusterNames []string `json:"clusterNames,omitempty"`
|
||||
|
||||
// ExcludedClusters is the list of clusters to be ignored.
|
||||
// +optional
|
||||
ExcludeClusters []string `json:"exclude,omitempty"`
|
||||
}
|
||||
|
||||
// FieldSelector is a field filter.
|
||||
type FieldSelector struct {
|
||||
// A list of field selector requirements.
|
||||
MatchExpressions []corev1.NodeSelectorRequirement `json:"matchExpressions,omitempty"`
|
||||
}
|
||||
|
||||
// ResourceSelector the resources will be selected.
|
||||
type ResourceSelector struct {
|
||||
// APIVersion represents the API version of the target resources.
|
||||
// +required
|
||||
APIVersion string `json:"apiVersion"`
|
||||
|
||||
// Kind represents the Kind of the target resources.
|
||||
// Kind represents the kind of the target resources.
|
||||
// +required
|
||||
Kind string `json:"kind"`
|
||||
|
||||
|
|
|
@ -8,8 +8,8 @@ package v1alpha1
|
|||
import (
|
||||
unsafe "unsafe"
|
||||
|
||||
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
|
||||
search "github.com/karmada-io/karmada/pkg/apis/search"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
conversion "k8s.io/apimachinery/pkg/conversion"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
|
@ -22,26 +22,6 @@ func init() {
|
|||
// RegisterConversions adds conversion functions to the given scheme.
|
||||
// Public to allow building arbitrary schemes.
|
||||
func RegisterConversions(s *runtime.Scheme) error {
|
||||
if err := s.AddGeneratedConversionFunc((*ClusterSelector)(nil), (*search.ClusterSelector)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_ClusterSelector_To_search_ClusterSelector(a.(*ClusterSelector), b.(*search.ClusterSelector), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*search.ClusterSelector)(nil), (*ClusterSelector)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_search_ClusterSelector_To_v1alpha1_ClusterSelector(a.(*search.ClusterSelector), b.(*ClusterSelector), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*FieldSelector)(nil), (*search.FieldSelector)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_FieldSelector_To_search_FieldSelector(a.(*FieldSelector), b.(*search.FieldSelector), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*search.FieldSelector)(nil), (*FieldSelector)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_search_FieldSelector_To_v1alpha1_FieldSelector(a.(*search.FieldSelector), b.(*FieldSelector), scope)
|
||||
}); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := s.AddGeneratedConversionFunc((*ResourceRegistry)(nil), (*search.ResourceRegistry)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||
return Convert_v1alpha1_ResourceRegistry_To_search_ResourceRegistry(a.(*ResourceRegistry), b.(*search.ResourceRegistry), scope)
|
||||
}); err != nil {
|
||||
|
@ -105,52 +85,6 @@ func RegisterConversions(s *runtime.Scheme) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_ClusterSelector_To_search_ClusterSelector(in *ClusterSelector, out *search.ClusterSelector, s conversion.Scope) error {
|
||||
out.LabelSelector = (*v1.LabelSelector)(unsafe.Pointer(in.LabelSelector))
|
||||
out.FieldSelector = (*search.FieldSelector)(unsafe.Pointer(in.FieldSelector))
|
||||
out.ClusterNames = *(*[]string)(unsafe.Pointer(&in.ClusterNames))
|
||||
out.ExcludeClusters = *(*[]string)(unsafe.Pointer(&in.ExcludeClusters))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha1_ClusterSelector_To_search_ClusterSelector is an autogenerated conversion function.
|
||||
func Convert_v1alpha1_ClusterSelector_To_search_ClusterSelector(in *ClusterSelector, out *search.ClusterSelector, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_ClusterSelector_To_search_ClusterSelector(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_search_ClusterSelector_To_v1alpha1_ClusterSelector(in *search.ClusterSelector, out *ClusterSelector, s conversion.Scope) error {
|
||||
out.LabelSelector = (*v1.LabelSelector)(unsafe.Pointer(in.LabelSelector))
|
||||
out.FieldSelector = (*FieldSelector)(unsafe.Pointer(in.FieldSelector))
|
||||
out.ClusterNames = *(*[]string)(unsafe.Pointer(&in.ClusterNames))
|
||||
out.ExcludeClusters = *(*[]string)(unsafe.Pointer(&in.ExcludeClusters))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_search_ClusterSelector_To_v1alpha1_ClusterSelector is an autogenerated conversion function.
|
||||
func Convert_search_ClusterSelector_To_v1alpha1_ClusterSelector(in *search.ClusterSelector, out *ClusterSelector, s conversion.Scope) error {
|
||||
return autoConvert_search_ClusterSelector_To_v1alpha1_ClusterSelector(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_FieldSelector_To_search_FieldSelector(in *FieldSelector, out *search.FieldSelector, s conversion.Scope) error {
|
||||
out.MatchExpressions = *(*[]corev1.NodeSelectorRequirement)(unsafe.Pointer(&in.MatchExpressions))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_v1alpha1_FieldSelector_To_search_FieldSelector is an autogenerated conversion function.
|
||||
func Convert_v1alpha1_FieldSelector_To_search_FieldSelector(in *FieldSelector, out *search.FieldSelector, s conversion.Scope) error {
|
||||
return autoConvert_v1alpha1_FieldSelector_To_search_FieldSelector(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_search_FieldSelector_To_v1alpha1_FieldSelector(in *search.FieldSelector, out *FieldSelector, s conversion.Scope) error {
|
||||
out.MatchExpressions = *(*[]corev1.NodeSelectorRequirement)(unsafe.Pointer(&in.MatchExpressions))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Convert_search_FieldSelector_To_v1alpha1_FieldSelector is an autogenerated conversion function.
|
||||
func Convert_search_FieldSelector_To_v1alpha1_FieldSelector(in *search.FieldSelector, out *FieldSelector, s conversion.Scope) error {
|
||||
return autoConvert_search_FieldSelector_To_v1alpha1_FieldSelector(in, out, s)
|
||||
}
|
||||
|
||||
func autoConvert_v1alpha1_ResourceRegistry_To_search_ResourceRegistry(in *ResourceRegistry, out *search.ResourceRegistry, s conversion.Scope) error {
|
||||
out.ObjectMeta = in.ObjectMeta
|
||||
if err := Convert_v1alpha1_ResourceRegistrySpec_To_search_ResourceRegistrySpec(&in.Spec, &out.Spec, s); err != nil {
|
||||
|
@ -206,7 +140,7 @@ func Convert_search_ResourceRegistryList_To_v1alpha1_ResourceRegistryList(in *se
|
|||
}
|
||||
|
||||
func autoConvert_v1alpha1_ResourceRegistrySpec_To_search_ResourceRegistrySpec(in *ResourceRegistrySpec, out *search.ResourceRegistrySpec, s conversion.Scope) error {
|
||||
out.ClusterSelectors = *(*[]search.ClusterSelector)(unsafe.Pointer(&in.ClusterSelectors))
|
||||
out.TargetCluster = (*policyv1alpha1.ClusterAffinity)(unsafe.Pointer(in.TargetCluster))
|
||||
out.ResourceSelectors = *(*[]search.ResourceSelector)(unsafe.Pointer(&in.ResourceSelectors))
|
||||
out.StatusUpdatePeriodSeconds = in.StatusUpdatePeriodSeconds
|
||||
return nil
|
||||
|
@ -218,7 +152,7 @@ func Convert_v1alpha1_ResourceRegistrySpec_To_search_ResourceRegistrySpec(in *Re
|
|||
}
|
||||
|
||||
func autoConvert_search_ResourceRegistrySpec_To_v1alpha1_ResourceRegistrySpec(in *search.ResourceRegistrySpec, out *ResourceRegistrySpec, s conversion.Scope) error {
|
||||
out.ClusterSelectors = *(*[]ClusterSelector)(unsafe.Pointer(&in.ClusterSelectors))
|
||||
out.TargetCluster = (*policyv1alpha1.ClusterAffinity)(unsafe.Pointer(in.TargetCluster))
|
||||
out.ResourceSelectors = *(*[]ResourceSelector)(unsafe.Pointer(&in.ResourceSelectors))
|
||||
out.StatusUpdatePeriodSeconds = in.StatusUpdatePeriodSeconds
|
||||
return nil
|
||||
|
|
|
@ -6,70 +6,11 @@
|
|||
package v1alpha1
|
||||
|
||||
import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ClusterSelector) DeepCopyInto(out *ClusterSelector) {
|
||||
*out = *in
|
||||
if in.LabelSelector != nil {
|
||||
in, out := &in.LabelSelector, &out.LabelSelector
|
||||
*out = new(v1.LabelSelector)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.FieldSelector != nil {
|
||||
in, out := &in.FieldSelector, &out.FieldSelector
|
||||
*out = new(FieldSelector)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.ClusterNames != nil {
|
||||
in, out := &in.ClusterNames, &out.ClusterNames
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.ExcludeClusters != nil {
|
||||
in, out := &in.ExcludeClusters, &out.ExcludeClusters
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterSelector.
|
||||
func (in *ClusterSelector) DeepCopy() *ClusterSelector {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ClusterSelector)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *FieldSelector) DeepCopyInto(out *FieldSelector) {
|
||||
*out = *in
|
||||
if in.MatchExpressions != nil {
|
||||
in, out := &in.MatchExpressions, &out.MatchExpressions
|
||||
*out = make([]corev1.NodeSelectorRequirement, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FieldSelector.
|
||||
func (in *FieldSelector) DeepCopy() *FieldSelector {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(FieldSelector)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ResourceRegistry) DeepCopyInto(out *ResourceRegistry) {
|
||||
*out = *in
|
||||
|
@ -134,12 +75,10 @@ func (in *ResourceRegistryList) DeepCopyObject() runtime.Object {
|
|||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ResourceRegistrySpec) DeepCopyInto(out *ResourceRegistrySpec) {
|
||||
*out = *in
|
||||
if in.ClusterSelectors != nil {
|
||||
in, out := &in.ClusterSelectors, &out.ClusterSelectors
|
||||
*out = make([]ClusterSelector, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
if in.TargetCluster != nil {
|
||||
in, out := &in.TargetCluster, &out.TargetCluster
|
||||
*out = new(policyv1alpha1.ClusterAffinity)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.ResourceSelectors != nil {
|
||||
in, out := &in.ResourceSelectors, &out.ResourceSelectors
|
||||
|
|
|
@ -6,70 +6,11 @@
|
|||
package search
|
||||
|
||||
import (
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
v1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ClusterSelector) DeepCopyInto(out *ClusterSelector) {
|
||||
*out = *in
|
||||
if in.LabelSelector != nil {
|
||||
in, out := &in.LabelSelector, &out.LabelSelector
|
||||
*out = new(v1.LabelSelector)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.FieldSelector != nil {
|
||||
in, out := &in.FieldSelector, &out.FieldSelector
|
||||
*out = new(FieldSelector)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.ClusterNames != nil {
|
||||
in, out := &in.ClusterNames, &out.ClusterNames
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.ExcludeClusters != nil {
|
||||
in, out := &in.ExcludeClusters, &out.ExcludeClusters
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ClusterSelector.
|
||||
func (in *ClusterSelector) DeepCopy() *ClusterSelector {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ClusterSelector)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *FieldSelector) DeepCopyInto(out *FieldSelector) {
|
||||
*out = *in
|
||||
if in.MatchExpressions != nil {
|
||||
in, out := &in.MatchExpressions, &out.MatchExpressions
|
||||
*out = make([]corev1.NodeSelectorRequirement, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new FieldSelector.
|
||||
func (in *FieldSelector) DeepCopy() *FieldSelector {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(FieldSelector)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ResourceRegistry) DeepCopyInto(out *ResourceRegistry) {
|
||||
*out = *in
|
||||
|
@ -134,12 +75,10 @@ func (in *ResourceRegistryList) DeepCopyObject() runtime.Object {
|
|||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ResourceRegistrySpec) DeepCopyInto(out *ResourceRegistrySpec) {
|
||||
*out = *in
|
||||
if in.ClusterSelectors != nil {
|
||||
in, out := &in.ClusterSelectors, &out.ClusterSelectors
|
||||
*out = make([]ClusterSelector, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
if in.TargetCluster != nil {
|
||||
in, out := &in.TargetCluster, &out.TargetCluster
|
||||
*out = new(v1alpha1.ClusterAffinity)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.ResourceSelectors != nil {
|
||||
in, out := &in.ResourceSelectors, &out.ResourceSelectors
|
||||
|
|
|
@ -69,8 +69,6 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
|
|||
"github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1.SpreadConstraint": schema_pkg_apis_policy_v1alpha1_SpreadConstraint(ref),
|
||||
"github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1.StaticClusterAssignment": schema_pkg_apis_policy_v1alpha1_StaticClusterAssignment(ref),
|
||||
"github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1.StaticClusterWeight": schema_pkg_apis_policy_v1alpha1_StaticClusterWeight(ref),
|
||||
"github.com/karmada-io/karmada/pkg/apis/search/v1alpha1.ClusterSelector": schema_pkg_apis_search_v1alpha1_ClusterSelector(ref),
|
||||
"github.com/karmada-io/karmada/pkg/apis/search/v1alpha1.FieldSelector": schema_pkg_apis_search_v1alpha1_FieldSelector(ref),
|
||||
"github.com/karmada-io/karmada/pkg/apis/search/v1alpha1.ResourceRegistry": schema_pkg_apis_search_v1alpha1_ResourceRegistry(ref),
|
||||
"github.com/karmada-io/karmada/pkg/apis/search/v1alpha1.ResourceRegistryList": schema_pkg_apis_search_v1alpha1_ResourceRegistryList(ref),
|
||||
"github.com/karmada-io/karmada/pkg/apis/search/v1alpha1.ResourceRegistrySpec": schema_pkg_apis_search_v1alpha1_ResourceRegistrySpec(ref),
|
||||
|
@ -2979,92 +2977,6 @@ func schema_pkg_apis_policy_v1alpha1_StaticClusterWeight(ref common.ReferenceCal
|
|||
}
|
||||
}
|
||||
|
||||
func schema_pkg_apis_search_v1alpha1_ClusterSelector(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "ClusterSelector represents the filter to select clusters.",
|
||||
Type: []string{"object"},
|
||||
Properties: map[string]spec.Schema{
|
||||
"labelSelector": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "LabelSelector is a filter to select member clusters by labels. If non-nil and non-empty, only the clusters match this filter will be selected.",
|
||||
Ref: ref("k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector"),
|
||||
},
|
||||
},
|
||||
"fieldSelector": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "FieldSelector is a filter to select member clusters by fields. If non-nil and non-empty, only the clusters match this filter will be selected.",
|
||||
Ref: ref("github.com/karmada-io/karmada/pkg/apis/search/v1alpha1.FieldSelector"),
|
||||
},
|
||||
},
|
||||
"clusterNames": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "ClusterNames is the list of clusters to be selected.",
|
||||
Type: []string{"array"},
|
||||
Items: &spec.SchemaOrArray{
|
||||
Schema: &spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"exclude": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "ExcludedClusters is the list of clusters to be ignored.",
|
||||
Type: []string{"array"},
|
||||
Items: &spec.SchemaOrArray{
|
||||
Schema: &spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"github.com/karmada-io/karmada/pkg/apis/search/v1alpha1.FieldSelector", "k8s.io/apimachinery/pkg/apis/meta/v1.LabelSelector"},
|
||||
}
|
||||
}
|
||||
|
||||
func schema_pkg_apis_search_v1alpha1_FieldSelector(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "FieldSelector is a field filter.",
|
||||
Type: []string{"object"},
|
||||
Properties: map[string]spec.Schema{
|
||||
"matchExpressions": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "A list of field selector requirements.",
|
||||
Type: []string{"array"},
|
||||
Items: &spec.SchemaOrArray{
|
||||
Schema: &spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Default: map[string]interface{}{},
|
||||
Ref: ref("k8s.io/api/core/v1.NodeSelectorRequirement"),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"k8s.io/api/core/v1.NodeSelectorRequirement"},
|
||||
}
|
||||
}
|
||||
|
||||
func schema_pkg_apis_search_v1alpha1_ResourceRegistry(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||
return common.OpenAPIDefinition{
|
||||
Schema: spec.Schema{
|
||||
|
@ -3171,18 +3083,10 @@ func schema_pkg_apis_search_v1alpha1_ResourceRegistrySpec(ref common.ReferenceCa
|
|||
Description: "ResourceRegistrySpec defines the desired state of ResourceRegistry.",
|
||||
Type: []string{"object"},
|
||||
Properties: map[string]spec.Schema{
|
||||
"clusterSelectors": {
|
||||
"targetCluster": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "ClusterSelectors represents the filter to select clusters.",
|
||||
Type: []string{"array"},
|
||||
Items: &spec.SchemaOrArray{
|
||||
Schema: &spec.Schema{
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Default: map[string]interface{}{},
|
||||
Ref: ref("github.com/karmada-io/karmada/pkg/apis/search/v1alpha1.ClusterSelector"),
|
||||
},
|
||||
},
|
||||
},
|
||||
Description: "TargetCluster is the cluster that the resource registry is targeting.",
|
||||
Ref: ref("github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1.ClusterAffinity"),
|
||||
},
|
||||
},
|
||||
"resourceSelectors": {
|
||||
|
@ -3207,11 +3111,11 @@ func schema_pkg_apis_search_v1alpha1_ResourceRegistrySpec(ref common.ReferenceCa
|
|||
},
|
||||
},
|
||||
},
|
||||
Required: []string{"clusterSelectors", "resourceSelectors"},
|
||||
Required: []string{"targetCluster", "resourceSelectors"},
|
||||
},
|
||||
},
|
||||
Dependencies: []string{
|
||||
"github.com/karmada-io/karmada/pkg/apis/search/v1alpha1.ClusterSelector", "github.com/karmada-io/karmada/pkg/apis/search/v1alpha1.ResourceSelector"},
|
||||
"github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1.ClusterAffinity", "github.com/karmada-io/karmada/pkg/apis/search/v1alpha1.ResourceSelector"},
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3261,7 +3165,7 @@ func schema_pkg_apis_search_v1alpha1_ResourceSelector(ref common.ReferenceCallba
|
|||
},
|
||||
"kind": {
|
||||
SchemaProps: spec.SchemaProps{
|
||||
Description: "Kind represents the Kind of the target resources.",
|
||||
Description: "Kind represents the kind of the target resources.",
|
||||
Default: "",
|
||||
Type: []string{"string"},
|
||||
Format: "",
|
||||
|
|
|
@ -105,8 +105,8 @@ func (c completedConfig) New(kubeClient kubernetes.Interface) (*APIServer, error
|
|||
searchREST := searchstorage.NewSearchREST(kubeClient)
|
||||
|
||||
v1alpha1search := map[string]rest.Storage{}
|
||||
v1alpha1search["resourceRegistry"] = resourceRegistryStorage.ResourceRegistry
|
||||
v1alpha1search["resourceRegistry/status"] = resourceRegistryStorage.Status
|
||||
v1alpha1search["resourceregistries"] = resourceRegistryStorage.ResourceRegistry
|
||||
v1alpha1search["resourceregistries/status"] = resourceRegistryStorage.Status
|
||||
v1alpha1search["search"] = searchREST
|
||||
apiGroupInfo.VersionedResourcesStorageMap["v1alpha1"] = v1alpha1search
|
||||
|
||||
|
|
|
@ -0,0 +1,391 @@
|
|||
package search
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/util/runtime"
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/cache"
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
"k8s.io/klog/v2"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client/apiutil"
|
||||
|
||||
clusterV1alpha1 "github.com/karmada-io/karmada/pkg/apis/cluster/v1alpha1"
|
||||
policyv1alpha1 "github.com/karmada-io/karmada/pkg/apis/policy/v1alpha1"
|
||||
"github.com/karmada-io/karmada/pkg/apis/search/v1alpha1"
|
||||
karmadaclientset "github.com/karmada-io/karmada/pkg/generated/clientset/versioned"
|
||||
informerfactory "github.com/karmada-io/karmada/pkg/generated/informers/externalversions"
|
||||
clusterlister "github.com/karmada-io/karmada/pkg/generated/listers/cluster/v1alpha1"
|
||||
"github.com/karmada-io/karmada/pkg/util"
|
||||
"github.com/karmada-io/karmada/pkg/util/gclient"
|
||||
"github.com/karmada-io/karmada/pkg/util/informermanager"
|
||||
"github.com/karmada-io/karmada/pkg/util/restmapper"
|
||||
)
|
||||
|
||||
type clusterRegistry struct {
|
||||
registries map[string]struct{}
|
||||
resources map[schema.GroupVersionResource]struct{}
|
||||
}
|
||||
|
||||
func (c *clusterRegistry) unregistry() bool {
|
||||
return len(c.registries) == 0
|
||||
}
|
||||
|
||||
// Controller ResourceRegistry controller
|
||||
type Controller struct {
|
||||
restConfig *rest.Config
|
||||
restMapper meta.RESTMapper
|
||||
informerFactory informerfactory.SharedInformerFactory
|
||||
clusterLister clusterlister.ClusterLister
|
||||
queue workqueue.RateLimitingInterface
|
||||
|
||||
clusterRegistry sync.Map
|
||||
|
||||
resourceHandler cache.ResourceEventHandler
|
||||
InformerManager informermanager.MultiClusterInformerManager
|
||||
}
|
||||
|
||||
// NewController returns a new ResourceRegistry controller
|
||||
func NewController(restConfig *rest.Config, rh cache.ResourceEventHandler) (*Controller, error) {
|
||||
karmadaClient := karmadaclientset.NewForConfigOrDie(restConfig)
|
||||
factory := informerfactory.NewSharedInformerFactory(karmadaClient, 0)
|
||||
clusterLister := factory.Cluster().V1alpha1().Clusters().Lister()
|
||||
restMapper, err := apiutil.NewDynamicRESTMapper(restConfig)
|
||||
if err != nil {
|
||||
klog.Errorf("Failed to create REST mapper: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
queue := workqueue.NewRateLimitingQueue(workqueue.DefaultControllerRateLimiter())
|
||||
|
||||
c := &Controller{
|
||||
restConfig: restConfig,
|
||||
informerFactory: factory,
|
||||
clusterLister: clusterLister,
|
||||
queue: queue,
|
||||
restMapper: restMapper,
|
||||
|
||||
resourceHandler: rh,
|
||||
InformerManager: informermanager.GetInstance(),
|
||||
}
|
||||
c.addAllEventHandlers()
|
||||
return c, nil
|
||||
}
|
||||
|
||||
// addAllEventHandlers adds all event handlers to the informer
|
||||
func (c *Controller) addAllEventHandlers() {
|
||||
clusterInformer := c.informerFactory.Cluster().V1alpha1().Clusters().Informer()
|
||||
clusterInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: c.addCluster,
|
||||
UpdateFunc: c.updateCluster,
|
||||
DeleteFunc: c.deleteCluster,
|
||||
})
|
||||
|
||||
resourceRegistryInformer := c.informerFactory.Search().V1alpha1().ResourceRegistries().Informer()
|
||||
resourceRegistryInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: c.addResourceRegistry,
|
||||
UpdateFunc: c.updateResourceRegistry,
|
||||
DeleteFunc: c.deleteResourceRegistry,
|
||||
})
|
||||
}
|
||||
|
||||
// Start the controller
|
||||
func (c *Controller) Start(stopCh <-chan struct{}) {
|
||||
klog.Infof("Starting karmada search controller")
|
||||
|
||||
defer runtime.HandleCrash()
|
||||
|
||||
c.informerFactory.Start(stopCh)
|
||||
c.informerFactory.WaitForCacheSync(stopCh)
|
||||
|
||||
go wait.Until(c.worker, time.Second, stopCh)
|
||||
|
||||
go func() {
|
||||
<-stopCh
|
||||
informermanager.StopInstance()
|
||||
klog.Infof("Shutting down karmada search controller")
|
||||
}()
|
||||
}
|
||||
|
||||
// worker processes the queue of resourceRegistry objects.
|
||||
func (c *Controller) worker() {
|
||||
for c.cacheNext() {
|
||||
}
|
||||
}
|
||||
|
||||
// cacheNext processes the next cluster object in the queue.
|
||||
func (c *Controller) cacheNext() bool {
|
||||
// Wait until there is a new item in the working queue
|
||||
key, shutdown := c.queue.Get()
|
||||
if shutdown {
|
||||
klog.Errorf("Fail to pop item from queue")
|
||||
return false
|
||||
}
|
||||
|
||||
// Tell the queue that we are done with processing this key. This unblocks the key for other workers
|
||||
// This allows safe parallel processing because two pods with the same key are never processed in
|
||||
// parallel.
|
||||
defer c.queue.Done(key)
|
||||
|
||||
err := c.doCacheCluster(key.(string))
|
||||
// Handle the error if something went wrong during the execution of the business logic
|
||||
c.handleErr(err, key)
|
||||
return true
|
||||
}
|
||||
|
||||
// handleErr checks if an error happened and makes sure we will retry later.
|
||||
func (c *Controller) handleErr(err error, key interface{}) {
|
||||
if err == nil {
|
||||
c.queue.Forget(key)
|
||||
return
|
||||
}
|
||||
|
||||
klog.Errorf("Error cache memeber cluster %v, %v", key, err)
|
||||
c.queue.AddRateLimited(key)
|
||||
}
|
||||
|
||||
// doCacheCluster processes the resourceRegistry object
|
||||
// TODO: update status
|
||||
func (c *Controller) doCacheCluster(cluster string) error {
|
||||
// STEP0: stop informer manager for the cluster which is not referenced by any `SearchRegistry` object.
|
||||
v, ok := c.clusterRegistry.Load(cluster)
|
||||
if !ok {
|
||||
klog.Infof("Cluster %s is not registered", cluster)
|
||||
return nil
|
||||
}
|
||||
|
||||
cr := v.(clusterRegistry)
|
||||
if cr.unregistry() {
|
||||
klog.Infof("try to stop cluster informer %s", cluster)
|
||||
c.InformerManager.Stop(cluster)
|
||||
return nil
|
||||
}
|
||||
|
||||
// STEP1: stop informer manager for the cluster which does not exist anymore.
|
||||
cls, err := c.clusterLister.Get(cluster)
|
||||
if err != nil {
|
||||
if apierrors.IsNotFound(err) {
|
||||
klog.Infof("try to stop cluster informer %s", cluster)
|
||||
c.InformerManager.Stop(cluster)
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
if !cls.DeletionTimestamp.IsZero() {
|
||||
klog.Infof("try to stop cluster informer %s", cluster)
|
||||
c.InformerManager.Stop(cluster)
|
||||
return nil
|
||||
}
|
||||
|
||||
// STEP2: added/updated cluster, builds an informer manager for a specific cluster.
|
||||
if !c.InformerManager.IsManagerExist(cluster) {
|
||||
klog.Info("try to build informer manager for cluster ", cluster)
|
||||
controlPlaneClient := gclient.NewForConfigOrDie(c.restConfig)
|
||||
|
||||
clusterDynamicClient, err := util.NewClusterDynamicClientSet(cluster, controlPlaneClient)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_ = c.InformerManager.ForCluster(cluster, clusterDynamicClient.DynamicClientSet, 0)
|
||||
}
|
||||
|
||||
if c.resourceHandler != nil {
|
||||
sci := c.InformerManager.GetSingleClusterManager(cluster)
|
||||
for gvr := range cr.resources {
|
||||
klog.Infof("try to start informer for %s, %v", cluster, gvr)
|
||||
// TODO: gvr exists check
|
||||
sci.ForResource(gvr, c.resourceHandler)
|
||||
}
|
||||
sci.Start()
|
||||
_ = sci.WaitForCacheSync()
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// addResourceRegistry parse the resourceRegistry object and add Cluster to the queue
|
||||
func (c *Controller) addResourceRegistry(obj interface{}) {
|
||||
rr := obj.(*v1alpha1.ResourceRegistry)
|
||||
resources := c.getResources(rr.Spec.ResourceSelectors)
|
||||
|
||||
for _, cluster := range c.getClusters(*rr.Spec.TargetCluster) {
|
||||
v, _ := c.clusterRegistry.LoadOrStore(cluster, clusterRegistry{
|
||||
resources: make(map[schema.GroupVersionResource]struct{}),
|
||||
registries: make(map[string]struct{})})
|
||||
cr := v.(clusterRegistry)
|
||||
|
||||
for _, r := range resources {
|
||||
cr.resources[r] = struct{}{}
|
||||
}
|
||||
cr.registries[rr.GetName()] = struct{}{}
|
||||
c.clusterRegistry.Store(cluster, cr)
|
||||
|
||||
c.queue.Add(cluster)
|
||||
}
|
||||
}
|
||||
|
||||
// updateResourceRegistry parse the resourceRegistry object and add (added/deleted) Cluster to the queue
|
||||
func (c *Controller) updateResourceRegistry(oldObj, newObj interface{}) {
|
||||
oldRR := oldObj.(*v1alpha1.ResourceRegistry)
|
||||
newRR := newObj.(*v1alpha1.ResourceRegistry)
|
||||
|
||||
// TODO: stop resource informers if it is not in the new resource registry
|
||||
resources := c.getResources(newRR.Spec.ResourceSelectors)
|
||||
|
||||
clusters := c.getClusters(*newRR.Spec.TargetCluster)
|
||||
clusterSets := make(map[string]struct{})
|
||||
|
||||
for _, cls := range clusters {
|
||||
v, _ := c.clusterRegistry.LoadOrStore(cls, clusterRegistry{
|
||||
resources: make(map[schema.GroupVersionResource]struct{}),
|
||||
registries: make(map[string]struct{})})
|
||||
cr := v.(clusterRegistry)
|
||||
|
||||
for _, r := range resources {
|
||||
cr.resources[r] = struct{}{}
|
||||
}
|
||||
cr.registries[newRR.GetName()] = struct{}{}
|
||||
c.clusterRegistry.Store(cls, cr)
|
||||
|
||||
clusterSets[cls] = struct{}{}
|
||||
c.queue.Add(cls)
|
||||
}
|
||||
|
||||
for _, cls := range c.getClusters(*oldRR.Spec.TargetCluster) {
|
||||
if _, ok := clusterSets[cls]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
v, ok := c.clusterRegistry.Load(cls)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
cr := v.(clusterRegistry)
|
||||
delete(cr.registries, oldRR.GetName())
|
||||
c.clusterRegistry.Store(cls, cr)
|
||||
|
||||
c.queue.Add(cls)
|
||||
}
|
||||
}
|
||||
|
||||
// deleteResourceRegistry parse the resourceRegistry object and add deleted Cluster to the queue
|
||||
func (c *Controller) deleteResourceRegistry(obj interface{}) {
|
||||
rr := obj.(*v1alpha1.ResourceRegistry)
|
||||
|
||||
for _, cluster := range c.getClusters(*rr.Spec.TargetCluster) {
|
||||
v, ok := c.clusterRegistry.Load(cluster)
|
||||
if !ok {
|
||||
return
|
||||
}
|
||||
cr := v.(clusterRegistry)
|
||||
delete(cr.registries, rr.GetName())
|
||||
c.clusterRegistry.Store(cluster, cr)
|
||||
|
||||
c.queue.Add(cluster)
|
||||
}
|
||||
}
|
||||
|
||||
// addCluster adds a cluster object to the queue if needed
|
||||
func (c *Controller) addCluster(obj interface{}) {
|
||||
cluster, ok := obj.(*clusterV1alpha1.Cluster)
|
||||
if !ok {
|
||||
klog.Errorf("cannot convert to *clusterV1alpha1.Cluster: %v", obj)
|
||||
return
|
||||
}
|
||||
|
||||
_, ok = c.clusterRegistry.Load(cluster.GetName())
|
||||
if ok {
|
||||
// unregistered cluster, do nothing.
|
||||
return
|
||||
}
|
||||
|
||||
c.queue.Add(cluster.GetName())
|
||||
}
|
||||
|
||||
// updateCluster TODO: rebuild informer if Cluster.Spec is changed
|
||||
func (c *Controller) updateCluster(oldObj, newObj interface{}) {}
|
||||
|
||||
// deleteCluster set cluster to not exists
|
||||
func (c *Controller) deleteCluster(obj interface{}) {
|
||||
cluster, ok := obj.(*clusterV1alpha1.Cluster)
|
||||
if !ok {
|
||||
klog.Errorf("cannot convert to *clusterV1alpha1.Cluster: %v", obj)
|
||||
return
|
||||
}
|
||||
|
||||
_, ok = c.clusterRegistry.Load(cluster.GetName())
|
||||
if !ok {
|
||||
// unregistered cluster, do nothing.
|
||||
return
|
||||
}
|
||||
|
||||
c.queue.Add(cluster.GetName())
|
||||
}
|
||||
|
||||
// getClusterAndResource returns the cluster and resources from the resourceRegistry object
|
||||
func (c *Controller) getClusters(affinity policyv1alpha1.ClusterAffinity) []string {
|
||||
clusters := make([]string, 0)
|
||||
lst, err := c.clusterLister.List(labels.Everything())
|
||||
if err != nil {
|
||||
klog.Errorf("failed to list clusters: %v", err)
|
||||
return clusters
|
||||
}
|
||||
for _, cls := range lst {
|
||||
if util.ClusterMatches(cls, affinity) {
|
||||
clusters = append(clusters, cls.GetName())
|
||||
}
|
||||
}
|
||||
return clusters
|
||||
}
|
||||
|
||||
// getClusterAndResource returns the cluster and resources from the resourceRegistry object
|
||||
func (c *Controller) getResources(selectors []v1alpha1.ResourceSelector) []schema.GroupVersionResource {
|
||||
resources := make([]schema.GroupVersionResource, 0)
|
||||
for _, rs := range selectors {
|
||||
gvr, err := restmapper.GetGroupVersionResource(
|
||||
c.restMapper, schema.FromAPIVersionAndKind(rs.APIVersion, rs.Kind),
|
||||
)
|
||||
if err != nil {
|
||||
klog.Errorf("failed to get gvr: %v", err)
|
||||
continue
|
||||
}
|
||||
resources = append(resources, gvr)
|
||||
}
|
||||
return resources
|
||||
}
|
||||
|
||||
// CachedResourceHandler is the default handler for resource events
|
||||
func CachedResourceHandler() cache.ResourceEventHandler {
|
||||
return &cache.ResourceEventHandlerFuncs{
|
||||
AddFunc: func(obj interface{}) {
|
||||
us, ok := obj.(*unstructured.Unstructured)
|
||||
if !ok {
|
||||
klog.Errorf("cannot convert to Unstructured: %v", obj)
|
||||
}
|
||||
klog.V(4).Infof("add resource %s, %s, %s, %s", us.GetAPIVersion(), us.GetKind(), us.GetNamespace(), us.GetName())
|
||||
},
|
||||
UpdateFunc: func(oldObj, newObj interface{}) {
|
||||
us, ok := newObj.(*unstructured.Unstructured)
|
||||
if !ok {
|
||||
klog.Errorf("cannot convert to Unstructured: %v", newObj)
|
||||
}
|
||||
klog.V(4).Infof("update resource %s, %s, %s, %s", us.GetAPIVersion(), us.GetKind(), us.GetNamespace(), us.GetName())
|
||||
},
|
||||
DeleteFunc: func(obj interface{}) {
|
||||
us, ok := obj.(*unstructured.Unstructured)
|
||||
if !ok {
|
||||
klog.Errorf("cannot convert to Unstructured: %v", obj)
|
||||
}
|
||||
klog.V(4).Infof("delete resource %s, %s, %s, %s", us.GetAPIVersion(), us.GetKind(), us.GetNamespace(), us.GetName())
|
||||
},
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue