Skip to content

Commit 2b7c07f

Browse files
committed
SecurityPolicy: per-mode service instances for T1/VPC mixed-mode
Replace the single SecurityPolicyService singleton with a per-mode map keyed by VPCMode (bool). Each SecurityPolicyReconciler now carries an isVPCMode field that determines which CRD it watches and which service instance it uses. In mixed-mode clusters, two independent reconcilers are registered — one for T1 namespaces, one for VPC namespaces.
1 parent f04226a commit 2b7c07f

19 files changed

Lines changed: 135 additions & 71 deletions

cmd/main.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,12 @@ func startServiceController(mgr manager.Manager, nsxClient *nsx.Client) {
250250
}
251251

252252
// Add controllers which can run in non-VPC mode
253-
reconcilerList = append(reconcilerList, securitypolicycontroller.NewSecurityPolicyReconciler(mgr, commonService, vpcService))
253+
if config.HasT1Namespaces() {
254+
reconcilerList = append(reconcilerList, securitypolicycontroller.NewSecurityPolicyReconciler(mgr, commonService, vpcService, false))
255+
}
256+
if config.HasVPCNamespaces() {
257+
reconcilerList = append(reconcilerList, securitypolicycontroller.NewSecurityPolicyReconciler(mgr, commonService, vpcService, true))
258+
}
254259

255260
// Add the NSXServiceAccount controller.
256261
if cf.EnableAntreaNSXInterworking {

pkg/clean/clean.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ func InitializeCleanupService(cf *config.NSXOperatorConfig, nsxClient *nsx.Clien
130130
}
131131
wrapInitializeSecurityPolicy := func(service common.Service) cleanupFunc {
132132
return func() (interface{}, error) {
133-
return securitypolicy.InitializeSecurityPolicy(service, vpcService, true)
133+
return securitypolicy.InitializeSecurityPolicy(service, vpcService, true, true)
134134
}
135135
}
136136
wrapInitializeVPC := func(service common.Service) cleanupFunc {

pkg/controllers/common/namespace_filter.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,3 +67,51 @@ func VPCNamespacePredicate(c client.Reader) predicate.Funcs {
6767
},
6868
}
6969
}
70+
71+
// isT1NamespaceByName fetches the Namespace by name and returns true if the namespace
72+
// is NOT a VPC namespace (i.e. it is a T1/legacy namespace).
73+
// Returns true when the namespace cannot be fetched (transient error or already
74+
// gone) so the Reconcile loop can decide what to do.
75+
func isT1NamespaceByName(c client.Reader, ns string) bool {
76+
namespace := &corev1.Namespace{}
77+
if err := c.Get(context.Background(), types.NamespacedName{Name: ns}, namespace); err != nil {
78+
if !apierrors.IsNotFound(err) {
79+
log.Error(err, "Failed to get Namespace for T1 predicate; allowing event through", "namespace", ns)
80+
}
81+
return true
82+
}
83+
return !config.IsVPCNamespace(namespace)
84+
}
85+
86+
// T1NamespacePredicate returns a predicate that filters events for T1-only
87+
// controllers. Events are passed when the resource's namespace is NOT a VPC namespace.
88+
// Behaviour by event type:
89+
// - Create / Update / Generic: allowed only for T1 namespaces.
90+
// - Delete: always allowed so the controller can clean up any existing NSX
91+
// resources even if the namespace is already gone.
92+
//
93+
// The namespace check is skipped for cluster-scoped resources (empty namespace),
94+
// which are always allowed through.
95+
func T1NamespacePredicate(c client.Reader) predicate.Funcs {
96+
isT1Ns := func(ns string) bool {
97+
if ns == "" {
98+
return true
99+
}
100+
return isT1NamespaceByName(c, ns)
101+
}
102+
103+
return predicate.Funcs{
104+
CreateFunc: func(e event.CreateEvent) bool {
105+
return isT1Ns(e.Object.GetNamespace())
106+
},
107+
UpdateFunc: func(e event.UpdateEvent) bool {
108+
return isT1Ns(e.ObjectNew.GetNamespace())
109+
},
110+
DeleteFunc: func(e event.DeleteEvent) bool {
111+
return true
112+
},
113+
GenericFunc: func(e event.GenericEvent) bool {
114+
return isT1Ns(e.Object.GetNamespace())
115+
},
116+
}
117+
}

pkg/controllers/networkpolicy/networkpolicy_controller.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ func NewNetworkPolicyReconciler(mgr ctrl.Manager, commonService servicecommon.Se
309309
Scheme: mgr.GetScheme(),
310310
Recorder: mgr.GetEventRecorderFor("networkpolicy-controller"),
311311
}
312-
networkPolicyReconcile.Service = securitypolicy.GetSecurityService(commonService, vpcService)
312+
networkPolicyReconcile.Service = securitypolicy.GetSecurityService(commonService, vpcService, true)
313313
networkPolicyReconcile.StatusUpdater = common.NewStatusUpdater(networkPolicyReconcile.Client, networkPolicyReconcile.Service.NSXConfig, networkPolicyReconcile.Recorder, MetricResType, "NetworkPolicy", "NetworkPolicy")
314314
return networkPolicyReconcile
315315
}

pkg/controllers/networkpolicy/networkpolicy_controller_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,7 @@ func fakeService() *securitypolicy.SecurityPolicyService {
111111
},
112112
},
113113
},
114+
VPCMode: true,
114115
}
115116
return service
116117
}
@@ -559,7 +560,7 @@ func TestStartNetworkPolicyController(t *testing.T) {
559560
patches.ApplyFunc(os.Exit, func(code int) {
560561
assert.FailNow(t, "os.Exit should not be called")
561562
})
562-
patches.ApplyFunc(securitypolicy.GetSecurityService, func(service common.Service, vpcService common.VPCServiceProvider) *securitypolicy.SecurityPolicyService {
563+
patches.ApplyFunc(securitypolicy.GetSecurityService, func(service common.Service, vpcService common.VPCServiceProvider, vpcMode bool) *securitypolicy.SecurityPolicyService {
563564
return fakeService()
564565
})
565566
patches.ApplyMethod(reflect.TypeOf(&NetworkPolicyReconciler{}), "Start", func(_ *NetworkPolicyReconciler, r ctrl.Manager) error {
@@ -574,7 +575,7 @@ func TestStartNetworkPolicyController(t *testing.T) {
574575
patches: func() *gomonkey.Patches {
575576
patches := gomonkey.ApplyFunc(ctrcommon.GenericGarbageCollector, func(cancel chan bool, timeout time.Duration, f func(ctx context.Context) error) {
576577
})
577-
patches.ApplyFunc(securitypolicy.GetSecurityService, func(service common.Service, vpcService common.VPCServiceProvider) *securitypolicy.SecurityPolicyService {
578+
patches.ApplyFunc(securitypolicy.GetSecurityService, func(service common.Service, vpcService common.VPCServiceProvider, vpcMode bool) *securitypolicy.SecurityPolicyService {
578579
return fakeService()
579580
})
580581
patches.ApplyPrivateMethod(reflect.TypeOf(&NetworkPolicyReconciler{}), "setupWithManager", func(_ *NetworkPolicyReconciler, mgr ctrl.Manager) error {

pkg/controllers/networkpolicy/pod_handler.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import (
1414
"sigs.k8s.io/controller-runtime/pkg/predicate"
1515
"sigs.k8s.io/controller-runtime/pkg/reconcile"
1616

17-
"github.com/vmware-tanzu/nsx-operator/pkg/nsx/services/securitypolicy"
1817
"github.com/vmware-tanzu/nsx-operator/pkg/util"
1918
)
2019

@@ -59,7 +58,7 @@ func (e *EnqueueRequestForPod) Raw(evt interface{}, q workqueue.TypedRateLimitin
5958
}
6059

6160
pod := obj.(*v1.Pod)
62-
vpcMode := securitypolicy.IsVPCEnabled(e.NetworkPolicyReconciler.Service)
61+
vpcMode := e.NetworkPolicyReconciler.Service.VPCMode
6362
if isInSysNs, err := util.IsSystemNamespace(e.Client, pod.Namespace, nil, vpcMode); err != nil {
6463
log.Error(err, "Failed to fetch namespace", "namespace", pod.Namespace)
6564
return

pkg/controllers/networkpolicy/pod_handler_test.go

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ import (
2020
"sigs.k8s.io/controller-runtime/pkg/event"
2121
"sigs.k8s.io/controller-runtime/pkg/reconcile"
2222

23-
"github.com/vmware-tanzu/nsx-operator/pkg/nsx/services/securitypolicy"
2423
"github.com/vmware-tanzu/nsx-operator/pkg/util"
2524
)
2625

@@ -148,10 +147,7 @@ func TestEnqueueRequestForPod_Raw(t *testing.T) {
148147
}
149148

150149
// Mock util.IsSystemNamespace
151-
patches := gomonkey.ApplyFunc(securitypolicy.IsVPCEnabled, func(_ interface{}) bool {
152-
return false
153-
})
154-
patches.ApplyFunc(util.IsSystemNamespace, func(client.Client, string, *v1.Namespace) (bool, error) {
150+
patches := gomonkey.ApplyFunc(util.IsSystemNamespace, func(client.Client, string, *v1.Namespace) (bool, error) {
155151
return tc.isSystemNs, tc.isSystemNsErr
156152
})
157153
// Mock reconcileNetworkPolicy to avoid actual reconciliation

pkg/controllers/securitypolicy/namespace_handler.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import (
1414
"sigs.k8s.io/controller-runtime/pkg/predicate"
1515
"sigs.k8s.io/controller-runtime/pkg/reconcile"
1616

17-
"github.com/vmware-tanzu/nsx-operator/pkg/nsx/services/securitypolicy"
1817
"github.com/vmware-tanzu/nsx-operator/pkg/util"
1918
)
2019

@@ -41,7 +40,7 @@ func (e *EnqueueRequestForNamespace) Generic(_ context.Context, _ event.GenericE
4140

4241
func (e *EnqueueRequestForNamespace) Update(_ context.Context, updateEvent event.UpdateEvent, l workqueue.TypedRateLimitingInterface[reconcile.Request]) {
4342
obj := updateEvent.ObjectNew.(*v1.Namespace)
44-
vpcMode := securitypolicy.IsVPCEnabled(e.SecurityPolicyReconciler.Service)
43+
vpcMode := e.SecurityPolicyReconciler.isVPCMode
4544
if isInSysNs, err := util.IsSystemNamespace(nil, "", obj, vpcMode); err != nil {
4645
log.Error(err, "Failed to fetch namespace", "namespace", obj.Name)
4746
return

pkg/controllers/securitypolicy/namespace_handler_test.go

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818
"sigs.k8s.io/controller-runtime/pkg/reconcile"
1919

2020
mock_client "github.com/vmware-tanzu/nsx-operator/pkg/mock/controller-runtime/client"
21-
"github.com/vmware-tanzu/nsx-operator/pkg/nsx/services/securitypolicy"
2221
"github.com/vmware-tanzu/nsx-operator/pkg/util"
2322
)
2423

@@ -139,9 +138,6 @@ func TestEnqueueRequestForNamespace_Update(t *testing.T) {
139138
) error {
140139
return nil
141140
})
142-
patches.ApplyFunc(securitypolicy.IsVPCEnabled, func(_ interface{}) bool {
143-
return false
144-
})
145141
patches.ApplyFunc(util.CheckPodHasNamedPort, func(pod v1.Pod, reason string) bool {
146142
return true
147143
})

pkg/controllers/securitypolicy/pod_handler.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import (
1515
"sigs.k8s.io/controller-runtime/pkg/predicate"
1616
"sigs.k8s.io/controller-runtime/pkg/reconcile"
1717

18-
"github.com/vmware-tanzu/nsx-operator/pkg/nsx/services/securitypolicy"
1918
"github.com/vmware-tanzu/nsx-operator/pkg/util"
2019
)
2120

@@ -65,7 +64,7 @@ func (e *EnqueueRequestForPod) Raw(evt interface{}, q workqueue.TypedRateLimitin
6564
}
6665

6766
pod := obj.(*v1.Pod)
68-
vpcMode := securitypolicy.IsVPCEnabled(e.SecurityPolicyReconciler.Service)
67+
vpcMode := e.SecurityPolicyReconciler.isVPCMode
6968
if isInSysNs, err := util.IsSystemNamespace(e.Client, pod.Namespace, nil, vpcMode); err != nil {
7069
log.Error(err, "Failed to fetch namespace", "namespace", pod.Namespace)
7170
return

0 commit comments

Comments
 (0)