Skip to content

Commit 4a6f13c

Browse files
committed
Add Inventory Controller watchers and VM tag management for VKS IDPS support
Add NSXServiceAccount and VirtualMachine watchers to the Inventory Controller, along with add/remove VM tag functionality in the Inventory Service. This enables tagging NSX Inventory VMs with nsx-op/cluster-name to support IDPS correlation of Kubernetes objects to IPs in VKS clusters. Key changes: - Add SupervisorClusterName field to NSXServiceAccountStatus and CRD schema, with backfill logic for already-realized ServiceAccounts - Implement VirtualMachine informer that enqueues running VKS VMs for tag processing, with a dedicated delete handler to ensure taggedVMs store cleanup (avoiding memory leak) - Implement NSXServiceAccount informer that enqueues VMs on SA realization and deletion for tag add/remove - Add SyncVirtualMachineTag with idempotent add/remove logic using NSX Fabric API (POST update_tags), backed by in-memory taggedVMs store rehydrated from NSX on startup via initTaggedVMs - Fix HandleHTTPResponse to accept 204 No Content and empty bodies - Add comprehensive unit tests for all handlers and service logic VGL-51541 Signed-off-by: Yun-Tang Hsu <yun-tang.hsu@broadcom.com>
1 parent 5434566 commit 4a6f13c

16 files changed

Lines changed: 1596 additions & 30 deletions

build/yaml/crd/legacy/nsx.vmware.com_nsxserviceaccounts.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,8 @@ spec:
154154
type: object
155155
reason:
156156
type: string
157+
supervisorClusterName:
158+
type: string
157159
secrets:
158160
items:
159161
properties:

pkg/apis/legacy/v1alpha1/nsxserviceaccount_types.go

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,14 +66,15 @@ type NSXServiceAccountStatus struct {
6666
Reason string `json:"reason,omitempty"`
6767
// Represents the realization status of a NSXServiceAccount's current state.
6868
// Known .status.conditions.type is: "Realized"
69-
Conditions []metav1.Condition `json:"conditions,omitempty"`
70-
VPCPath string `json:"vpcPath,omitempty"`
71-
NSXManagers []string `json:"nsxManagers,omitempty"`
72-
ProxyEndpoints NSXProxyEndpoint `json:"proxyEndpoints,omitempty"`
73-
ClusterID string `json:"clusterID,omitempty"`
74-
ClusterName string `json:"clusterName,omitempty"`
75-
Secrets []NSXSecret `json:"secrets,omitempty"`
76-
NSXRestoreStatus *NSXRestoreStatus `json:"nsxRestoreStatus,omitempty"`
69+
Conditions []metav1.Condition `json:"conditions,omitempty"`
70+
VPCPath string `json:"vpcPath,omitempty"`
71+
NSXManagers []string `json:"nsxManagers,omitempty"`
72+
ProxyEndpoints NSXProxyEndpoint `json:"proxyEndpoints,omitempty"`
73+
ClusterID string `json:"clusterID,omitempty"`
74+
ClusterName string `json:"clusterName,omitempty"`
75+
SupervisorClusterName string `json:"supervisorClusterName,omitempty"`
76+
Secrets []NSXSecret `json:"secrets,omitempty"`
77+
NSXRestoreStatus *NSXRestoreStatus `json:"nsxRestoreStatus,omitempty"`
7778
}
7879

7980
// +genclient

pkg/controllers/inventory/inventory_controller.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,8 @@ var (
4545
watchIngress,
4646
watchNode,
4747
watchNetworkPolicy,
48+
watchNSXServiceAccount,
49+
watchVirtualMachine,
4850
}
4951
)
5052

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
package inventory
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
vmv1alpha1 "github.com/vmware-tanzu/vm-operator/api/v1alpha1"
8+
"k8s.io/client-go/tools/cache"
9+
ctrl "sigs.k8s.io/controller-runtime"
10+
"sigs.k8s.io/controller-runtime/pkg/client"
11+
12+
nsxvmwarecomv1alpha1 "github.com/vmware-tanzu/nsx-operator/pkg/apis/legacy/v1alpha1"
13+
"github.com/vmware-tanzu/nsx-operator/pkg/nsx/services/inventory"
14+
)
15+
16+
func watchNSXServiceAccount(c *InventoryController, mgr ctrl.Manager) error {
17+
nsxSAInformer, err := mgr.GetCache().GetInformer(context.Background(), &nsxvmwarecomv1alpha1.NSXServiceAccount{})
18+
if err != nil {
19+
log.Error(err, "Failed to create NSXServiceAccount informer")
20+
return err
21+
}
22+
23+
_, err = nsxSAInformer.AddEventHandler(cache.ResourceEventHandlerFuncs{
24+
AddFunc: func(obj interface{}) {
25+
c.handleNSXServiceAccount(obj)
26+
},
27+
UpdateFunc: func(oldObj, newObj interface{}) {
28+
c.handleNSXServiceAccount(newObj)
29+
},
30+
DeleteFunc: func(obj interface{}) {
31+
c.handleNSXServiceAccountDelete(obj)
32+
},
33+
})
34+
if err != nil {
35+
log.Error(err, "Failed to add NSXServiceAccount event handler")
36+
return err
37+
}
38+
return nil
39+
}
40+
41+
func (c *InventoryController) handleNSXServiceAccount(obj interface{}) {
42+
var nsxSA *nsxvmwarecomv1alpha1.NSXServiceAccount
43+
switch v := obj.(type) {
44+
case *nsxvmwarecomv1alpha1.NSXServiceAccount:
45+
nsxSA = v
46+
case cache.DeletedFinalStateUnknown:
47+
var ok bool
48+
nsxSA, ok = v.Obj.(*nsxvmwarecomv1alpha1.NSXServiceAccount)
49+
if !ok {
50+
err := fmt.Errorf("obj is not valid *NSXServiceAccount")
51+
log.Error(err, "DeletedFinalStateUnknown Obj is not *NSXServiceAccount")
52+
return
53+
}
54+
}
55+
56+
if nsxSA.Status.Phase != nsxvmwarecomv1alpha1.NSXServiceAccountPhaseRealized {
57+
log.Debug("Skip NSXServiceAccount not yet realized", "namespace", nsxSA.Namespace, "name", nsxSA.Name)
58+
return
59+
}
60+
61+
c.enqueueVMsForCluster(nsxSA)
62+
}
63+
64+
func (c *InventoryController) handleNSXServiceAccountDelete(obj interface{}) {
65+
var nsxSA *nsxvmwarecomv1alpha1.NSXServiceAccount
66+
switch v := obj.(type) {
67+
case *nsxvmwarecomv1alpha1.NSXServiceAccount:
68+
nsxSA = v
69+
case cache.DeletedFinalStateUnknown:
70+
var ok bool
71+
nsxSA, ok = v.Obj.(*nsxvmwarecomv1alpha1.NSXServiceAccount)
72+
if !ok {
73+
err := fmt.Errorf("obj is not valid *NSXServiceAccount")
74+
log.Error(err, "DeletedFinalStateUnknown Obj is not *NSXServiceAccount")
75+
return
76+
}
77+
}
78+
79+
log.Info("NSXServiceAccount deleted, enqueuing VMs for tag removal", "namespace", nsxSA.Namespace, "name", nsxSA.Name)
80+
c.enqueueVMsForCluster(nsxSA)
81+
}
82+
83+
// enqueueVMsForCluster lists all VirtualMachines in the NSXServiceAccount's namespace
84+
// and enqueues them to the inventory queue for VM tag processing.
85+
func (c *InventoryController) enqueueVMsForCluster(nsxSA *nsxvmwarecomv1alpha1.NSXServiceAccount) {
86+
vmList := &vmv1alpha1.VirtualMachineList{}
87+
if err := c.Client.List(context.Background(), vmList, &client.ListOptions{
88+
Namespace: nsxSA.Namespace,
89+
}); err != nil {
90+
log.Error(err, "Failed to list VirtualMachines for NSXServiceAccount", "namespace", nsxSA.Namespace)
91+
return
92+
}
93+
94+
for i := range vmList.Items {
95+
vm := &vmList.Items[i]
96+
if !belongsToVKSCluster(vm) {
97+
continue
98+
}
99+
log.Debug("Enqueuing VM from NSXServiceAccount event", "namespace", vm.Namespace, "name", vm.Name)
100+
key, _ := keyFunc(vm)
101+
c.inventoryObjectQueue.Add(inventory.InventoryKey{
102+
InventoryType: inventory.InventoryVirtualMachine,
103+
ExternalId: vm.Status.InstanceUUID,
104+
Key: key,
105+
})
106+
}
107+
}

0 commit comments

Comments
 (0)