Skip to content

Commit

Permalink
perf: improve member cluster member agent (Azure#677)
Browse files Browse the repository at this point in the history
* iprove member cluster member agent

* fix error

* minor fix

* compare using GVK

* minor field fix

* address comments

* fix fmt

* minor fix

* address comment
  • Loading branch information
britaniar authored Feb 21, 2024
1 parent 40242db commit d23d9d3
Show file tree
Hide file tree
Showing 10 changed files with 294 additions and 133 deletions.
12 changes: 11 additions & 1 deletion pkg/controllers/clusterresourceplacement/resource_selector.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,20 @@ func (r *Reconciler) gatherSelectedResource(placement string, selectors []fleetv
}
// sort the resources in strict order so that we will get the stable list of manifest so that
// the generated work object doesn't change between reconcile loops
sortResources(resources)

return resources, nil
}
func sortResources(resources []runtime.Object) {
sort.Slice(resources, func(i, j int) bool {
obj1 := resources[i].DeepCopyObject().(*unstructured.Unstructured)
obj2 := resources[j].DeepCopyObject().(*unstructured.Unstructured)
if obj1.GetObjectKind().GroupVersionKind().String() == utils.NamespaceMetaGVK.String() || obj2.GetObjectKind().GroupVersionKind().String() == utils.NamespaceMetaGVK.String() {
return obj1.GetObjectKind().GroupVersionKind().String() == utils.NamespaceMetaGVK.String()
}
if obj1.GetObjectKind().GroupVersionKind().String() == utils.CRDMetaGVK.String() || obj2.GetObjectKind().GroupVersionKind().String() == utils.CRDMetaGVK.String() {
return obj1.GetObjectKind().GroupVersionKind().String() == utils.CRDMetaGVK.String()
}
// compare group/version;kind
gvkComp := strings.Compare(obj1.GroupVersionKind().String(), obj2.GroupVersionKind().String())
if gvkComp > 0 {
Expand All @@ -112,7 +123,6 @@ func (r *Reconciler) gatherSelectedResource(placement string, selectors []fleetv
return strings.Compare(fmt.Sprintf("%s/%s", obj1.GetNamespace(), obj1.GetName()),
fmt.Sprintf("%s/%s", obj2.GetNamespace(), obj2.GetName())) > 0
})
return resources, nil
}

// fetchClusterScopedResources retrieves the objects based on the selector.
Expand Down
77 changes: 77 additions & 0 deletions pkg/controllers/clusterresourceplacement/resource_selector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -794,3 +794,80 @@ func createResourceContentForTest(t *testing.T, obj interface{}) *fleetv1beta1.R
},
}
}

func TestSortResource(t *testing.T) {
// Create the Namespace object
namespace := &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
"kind": "Namespace",
"metadata": map[string]interface{}{
"name": "test",
},
},
}

// Create the Deployment object
deployment := &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "test-nginx",
"namespace": "test",
},
},
}

// Create the CustomResourceDefinition object
crd := &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apiextensions.k8s.io/v1",
"kind": "CustomResourceDefinition",
"metadata": map[string]interface{}{
"name": "test-crd",
},
},
}

// Create the ClusterRole object
clusterRole := &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "rbac.authorization.k8s.io/v1",
"kind": "ClusterRole",
"metadata": map[string]interface{}{
"name": "test-clusterrole",
},
},
}

tests := map[string]struct {
resources []runtime.Object
want []runtime.Object
}{
"should gather selected resources with Namespace in front": {
resources: []runtime.Object{deployment, namespace},
want: []runtime.Object{namespace, deployment},
},
"should gather selected resources with CRD in front": {
resources: []runtime.Object{clusterRole, crd},
want: []runtime.Object{crd, clusterRole},
},
"should gather selected resources with CRD or Namespace in front": {
resources: []runtime.Object{deployment, clusterRole, crd, namespace},
want: []runtime.Object{namespace, crd, clusterRole, deployment},
},
}

for testName, tt := range tests {
t.Run(testName, func(t *testing.T) {
sortResources(tt.resources)

// Check that the returned resources match the expected resources
diff := cmp.Diff(tt.want, tt.resources)
if diff != "" {
t.Errorf("sortResources() mismatch (-want +got):\n%s", diff)
}
})
}
}
99 changes: 99 additions & 0 deletions pkg/utils/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,9 @@ import (
corev1 "k8s.io/api/core/v1"
discoveryv1 "k8s.io/api/discovery/v1"
rbacv1 "k8s.io/api/rbac/v1"
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
Expand All @@ -24,6 +26,7 @@ import (
"k8s.io/klog/v2"
workv1alpha1 "sigs.k8s.io/work-api/pkg/apis/v1alpha1"

fleetnetworkingv1alpha1 "go.goms.io/fleet-networking/api/v1alpha1"
clusterv1beta1 "go.goms.io/fleet/apis/cluster/v1beta1"
placementv1beta1 "go.goms.io/fleet/apis/placement/v1beta1"
fleetv1alpha1 "go.goms.io/fleet/apis/v1alpha1"
Expand Down Expand Up @@ -166,6 +169,102 @@ var (
Version: corev1.SchemeGroupVersion.Version,
Kind: "ConfigMap",
}

NamespaceMetaGVK = metav1.GroupVersionKind{
Group: corev1.GroupName,
Version: corev1.SchemeGroupVersion.Version,
Kind: "Namespace",
}

RoleMetaGVK = metav1.GroupVersionKind{
Group: rbacv1.SchemeGroupVersion.Group,
Version: rbacv1.SchemeGroupVersion.Version,
Kind: "Role",
}

RoleBindingMetaGVK = metav1.GroupVersionKind{
Group: rbacv1.SchemeGroupVersion.Group,
Version: rbacv1.SchemeGroupVersion.Version,
Kind: "RoleBinding",
}

PodMetaGVK = metav1.GroupVersionKind{
Group: corev1.SchemeGroupVersion.Group,
Version: corev1.SchemeGroupVersion.Version,
Kind: "Pod",
}

CRDMetaGVK = metav1.GroupVersionKind{
Group: apiextensionsv1.SchemeGroupVersion.Group,
Version: apiextensionsv1.SchemeGroupVersion.Version,
Kind: "CustomResourceDefinition",
}

V1Alpha1MCMetaGVK = metav1.GroupVersionKind{
Group: fleetv1alpha1.GroupVersion.Group,
Version: fleetv1alpha1.GroupVersion.Version,
Kind: "MemberCluster",
}

V1Alpha1IMCMetaGVK = metav1.GroupVersionKind{
Group: fleetv1alpha1.GroupVersion.Group,
Version: fleetv1alpha1.GroupVersion.Version,
Kind: "InternalMemberCluster",
}

V1Alpha1WorkMetaGVK = metav1.GroupVersionKind{
Group: workv1alpha1.GroupVersion.Group,
Version: workv1alpha1.GroupVersion.Version,
Kind: "Work",
}

MCMetaGVK = metav1.GroupVersionKind{
Group: clusterv1beta1.GroupVersion.Group,
Version: clusterv1beta1.GroupVersion.Version,
Kind: "MemberCluster",
}

IMCMetaGVK = metav1.GroupVersionKind{
Group: clusterv1beta1.GroupVersion.Group,
Version: clusterv1beta1.GroupVersion.Version,
Kind: "InternalMemberCluster",
}

WorkV1Beta1MetaGVK = metav1.GroupVersionKind{
Group: placementv1beta1.GroupVersion.Group,
Version: placementv1beta1.GroupVersion.Version,
Kind: "Work",
}

EventMetaGVK = metav1.GroupVersionKind{
Group: corev1.SchemeGroupVersion.Group,
Version: corev1.SchemeGroupVersion.Version,
Kind: "Event",
}

EndpointSliceExportMetaGVK = metav1.GroupVersionKind{
Group: fleetnetworkingv1alpha1.GroupVersion.Group,
Version: fleetnetworkingv1alpha1.GroupVersion.Version,
Kind: "EndpointSliceExport",
}

EndpointSliceImportMetaGVK = metav1.GroupVersionKind{
Group: fleetnetworkingv1alpha1.GroupVersion.Group,
Version: fleetnetworkingv1alpha1.GroupVersion.Version,
Kind: "EndpointSliceImport",
}

InternalServiceExportMetaGVK = metav1.GroupVersionKind{
Group: fleetnetworkingv1alpha1.GroupVersion.Group,
Version: fleetnetworkingv1alpha1.GroupVersion.Version,
Kind: "InternalServiceExport",
}

InternalServiceImportMetaGVK = metav1.GroupVersionKind{
Group: fleetnetworkingv1alpha1.GroupVersion.Group,
Version: fleetnetworkingv1alpha1.GroupVersion.Version,
Kind: "InternalServiceImport",
}
)

// RandSecureInt returns a uniform random value in [1, max] or panic.
Expand Down
12 changes: 6 additions & 6 deletions pkg/webhook/fleetresourcehandler/fleetresourcehandler_webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,22 +55,22 @@ func (v *fleetResourceValidator) Handle(ctx context.Context, req admission.Reque
var response admission.Response
if req.Operation == admissionv1.Create || req.Operation == admissionv1.Update || req.Operation == admissionv1.Delete {
switch {
case req.Kind == validation.CRDGVK:
case req.Kind == utils.CRDMetaGVK:
klog.V(2).InfoS("handling CRD resource", "name", req.Name, "operation", req.Operation, "subResource", req.SubResource)
response = v.handleCRD(req)
case req.Kind == validation.V1Alpha1MCGVK:
case req.Kind == utils.V1Alpha1MCMetaGVK:
klog.V(2).InfoS("handling v1alpha1 member cluster resource", "name", req.Name, "operation", req.Operation, "subResource", req.SubResource)
response = v.handleV1Alpha1MemberCluster(req)
case req.Kind == validation.MCGVK:
case req.Kind == utils.MCMetaGVK:
klog.V(2).InfoS("handling member cluster resource", "name", req.Name, "operation", req.Operation, "subResource", req.SubResource)
response = v.handleMemberCluster(req)
case req.Kind == validation.NamespaceGVK:
case req.Kind == utils.NamespaceMetaGVK:
klog.V(2).InfoS("handling namespace resource", "name", req.Name, "operation", req.Operation, "subResource", req.SubResource)
response = v.handleNamespace(req)
case req.Kind == validation.V1Alpha1IMCGVK || req.Kind == validation.V1Alpha1WorkGVK || req.Kind == validation.IMCGVK || req.Kind == validation.WorkGVK || req.Kind == validation.EndpointSliceExportGVK || req.Kind == validation.EndpointSliceImportGVK || req.Kind == validation.InternalServiceExportGVK || req.Kind == validation.InternalServiceImportGVK:
case req.Kind == utils.V1Alpha1IMCMetaGVK || req.Kind == utils.V1Alpha1WorkMetaGVK || req.Kind == utils.IMCMetaGVK || req.Kind == utils.WorkV1Beta1MetaGVK || req.Kind == utils.EndpointSliceExportMetaGVK || req.Kind == utils.EndpointSliceImportMetaGVK || req.Kind == utils.InternalServiceExportMetaGVK || req.Kind == utils.InternalServiceImportMetaGVK:
klog.V(2).InfoS("handling fleet owned namespaced resource in fleet reserved namespaces", "GVK", req.RequestKind, "namespacedName", namespacedName, "operation", req.Operation, "subResource", req.SubResource)
response = v.handleFleetReservedNamespacedResource(ctx, req)
case req.Kind == validation.EventGVK:
case req.Kind == utils.EventMetaGVK:
klog.V(3).InfoS("handling event resource", "namespacedName", namespacedName, "operation", req.Operation, "subResource", req.SubResource)
response = v.handleEvent(ctx, req)
case req.Namespace != "":
Expand Down
Loading

0 comments on commit d23d9d3

Please sign in to comment.