From a287bed75538c313d4ede915114b43fdba8db6bb Mon Sep 17 00:00:00 2001 From: aasifkhan7 Date: Sun, 29 Dec 2024 18:41:09 +0530 Subject: [PATCH 1/3] remove unused network policy as well --- pkg/determiner/determiner.go | 25 ++++++++++++++++++++++++- pkg/resource/resource.go | 16 ++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/pkg/determiner/determiner.go b/pkg/determiner/determiner.go index 1496546..f086523 100644 --- a/pkg/determiner/determiner.go +++ b/pkg/determiner/determiner.go @@ -138,12 +138,35 @@ func (d *determiner) DetermineDeletion(ctx context.Context, info *cliresource.In case resource.KindHorizontalPodAutoscaler: return d.determineDeletionHorizontalPodAutoscaler(ctx, info) - + case resource.KindNetworkPolicy: + return d.determineDeletionNetworkPolicy(info) default: return false, fmt.Errorf("unsupported kind: %s/%s", kind, info.Name) } } +func (d *determiner) determineDeletionNetworkPolicy(info *cliresource.Info) (bool, error) { + np, err := resource.ObjectToNetworkPolicy(info.Object) + if err != nil { + return false, err + } + + // Get the selector from the Network Policy + selector, err := metav1.LabelSelectorAsSelector(&np.Spec.PodSelector) + if err != nil { + return false, fmt.Errorf("invalid label selector (%s): %w", np.Name, err) + } + + // Iterate over pods to check if any match the selector + for _, pod := range d.pods { + if selector.Matches(labels.Set(pod.Labels)) { + return false, nil // Pod matches the selector, so the Network Policy is used + } + } + + return true, nil // No pods match the selector, so the Network Policy is unused +} + func (d *determiner) determineDeletionPod(info *cliresource.Info) (bool, error) { pod, err := resource.ObjectToPod(info.Object) if err != nil { diff --git a/pkg/resource/resource.go b/pkg/resource/resource.go index df0fd81..46b2ff1 100644 --- a/pkg/resource/resource.go +++ b/pkg/resource/resource.go @@ -7,6 +7,7 @@ import ( corev1 "k8s.io/api/core/v1" policyv1beta1 "k8s.io/api/policy/v1beta1" "k8s.io/apimachinery/pkg/runtime" + networkingv1 "k8s.io/api/networking/v1" ) const ( @@ -20,6 +21,7 @@ const ( KindJob = "Job" KindPodDisruptionBudget = "PodDisruptionBudget" KindHorizontalPodAutoscaler = "HorizontalPodAutoscaler" + KindNetworkPolicy = "NetworkPolicy" ) var unstructuredConverter = runtime.DefaultUnstructuredConverter @@ -108,6 +110,20 @@ func ObjectToHorizontalPodAutoscaler(obj runtime.Object) (*autoscalingv1.Horizon return &hpa, nil } +func ObjectToNetworkPolicy(obj runtime.Object) (*networkingv1.NetworkPolicy, error) { + u, err := toUnstructured(obj) + if err != nil { + return nil, err + } + + var np networkingv1.NetworkPolicy + if err := fromUnstructured(u, &np); err != nil { + return nil, err + } + + return &np, nil +} + func toUnstructured(obj runtime.Object) (map[string]interface{}, error) { return unstructuredConverter.ToUnstructured(obj) } From abbcafa3ba43a0a5f059dddb659758534755fc99 Mon Sep 17 00:00:00 2001 From: aasifkhan7 Date: Sun, 29 Dec 2024 18:41:54 +0530 Subject: [PATCH 2/3] Update determiner.go --- pkg/determiner/determiner.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/determiner/determiner.go b/pkg/determiner/determiner.go index f086523..216814c 100644 --- a/pkg/determiner/determiner.go +++ b/pkg/determiner/determiner.go @@ -139,7 +139,7 @@ func (d *determiner) DetermineDeletion(ctx context.Context, info *cliresource.In case resource.KindHorizontalPodAutoscaler: return d.determineDeletionHorizontalPodAutoscaler(ctx, info) case resource.KindNetworkPolicy: - return d.determineDeletionNetworkPolicy(info) + return d.determineDeletionNetworkPolicy(info) default: return false, fmt.Errorf("unsupported kind: %s/%s", kind, info.Name) } From 09004971620d1cefdd0b44079556274ad100b440 Mon Sep 17 00:00:00 2001 From: aasifkhan7 Date: Mon, 30 Dec 2024 20:47:12 +0530 Subject: [PATCH 3/3] added Test_determiner_determineDeletionNetworkPolicy --- pkg/determiner/determiner_test.go | 106 ++++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) diff --git a/pkg/determiner/determiner_test.go b/pkg/determiner/determiner_test.go index 3bf0a8e..3364038 100644 --- a/pkg/determiner/determiner_test.go +++ b/pkg/determiner/determiner_test.go @@ -754,3 +754,109 @@ func Test_determiner_determineUsedSecret(t *testing.T) { }) } } + +func Test_determiner_determineDeletionNetworkPolicy(t *testing.T) { + const ( + fakeNetworkPolicy = "fake-np" + fakePodLabelKey = "app" + fakePodLabelValue = "nginx" + ) + + type fields struct { + pods []*corev1.Pod + } + type args struct { + info *cliresource.Info + } + tests := []struct { + name string + fields fields + args args + want bool + wantErr bool + }{ + { + name: "NetworkPolicy should not be deleted when it matches a pod", + fields: fields{ + pods: []*corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + fakePodLabelKey: fakePodLabelValue, + }, + }, + }, + }, + }, + args: args{ + info: &cliresource.Info{ + Name: fakeNetworkPolicy, + Object: &networkingv1.NetworkPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: resource.KindNetworkPolicy, + }, + Spec: networkingv1.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + fakePodLabelKey: fakePodLabelValue, + }, + }, + }, + }, + }, + }, + want: false, + wantErr: false, + }, + { + name: "NetworkPolicy should be deleted when it does not match any pod", + fields: fields{ + pods: []*corev1.Pod{ + { + ObjectMeta: metav1.ObjectMeta{ + Labels: map[string]string{ + fakePodLabelKey: "other", + }, + }, + }, + }, + }, + args: args{ + info: &cliresource.Info{ + Name: fakeNetworkPolicy, + Object: &networkingv1.NetworkPolicy{ + TypeMeta: metav1.TypeMeta{ + Kind: resource.KindNetworkPolicy, + }, + Spec: networkingv1.NetworkPolicySpec{ + PodSelector: metav1.LabelSelector{ + MatchLabels: map[string]string{ + fakePodLabelKey: fakePodLabelValue, + }, + }, + }, + }, + }, + }, + want: true, + wantErr: false, + }, + } + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + d := &determiner{ + pods: tt.fields.pods, + } + got, err := d.determineDeletionNetworkPolicy(tt.args.info) + if (err != nil) != tt.wantErr { + t.Errorf("determineDeletionNetworkPolicy() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("determineDeletionNetworkPolicy() = %v, want %v", got, tt.want) + } + }) + } +}