Repository: vmware-tanzu/nsx-operator
Pull request #510: Implement image fetcher feature
Author: login: zhengxiexie
Labels: name: cla-not-required
Created: 2024-02-01T10:43:24Z | Merged: 2025-04-21T09:30:44Z

Sync iaas.vmware.com/image-fetcher: "true" and namespace_uid label of subnetport with tags of nsx-t. 


Diff:
diff --git a/pkg/controllers/pod/pod_controller.go b/pkg/controllers/pod/pod_controller.go
index 00c9c1c07..a820488ea 100644
--- a/pkg/controllers/pod/pod_controller.go
+++ b/pkg/controllers/pod/pod_controller.go
@@ -174,7 +174,7 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R
 			r.StatusUpdater.UpdateFail(ctx, pod, err, "", setPodReadyStatusFalse)
 			return common.ResultRequeue, err
 		}
-		_, err = r.SubnetPortService.CreateOrUpdateSubnetPort(pod, nsxSubnet, contextID, &pod.ObjectMeta.Labels)
+		_, err = r.SubnetPortService.CreateOrUpdateSubnetPort(pod, nsxSubnet, contextID, &pod.ObjectMeta.Labels, false)
 		if err != nil {
 			r.StatusUpdater.UpdateFail(ctx, pod, err, "", setPodReadyStatusFalse)
 			return common.ResultRequeue, err
diff --git a/pkg/controllers/subnetport/subnetport_controller.go b/pkg/controllers/subnetport/subnetport_controller.go
index 3f42fcef2..f6b5c9caa 100644
--- a/pkg/controllers/subnetport/subnetport_controller.go
+++ b/pkg/controllers/subnetport/subnetport_controller.go
@@ -117,7 +117,17 @@ func (r *SubnetPortReconciler) Reconcile(ctx context.Context, req ctrl.Request)
 			r.StatusUpdater.UpdateFail(ctx, subnetPort, err, fmt.Sprintf("Failed to get Subnet by path: %s", nsxSubnetPath), setSubnetPortReadyStatusFalse, r.SubnetPortService)
 			return common.ResultRequeue, err
 		}
-		nsxSubnetPortState, err := r.SubnetPortService.CreateOrUpdateSubnetPort(subnetPort, nsxSubnet, "", labels)
+
+		isVmSubnetPort := true
+		if value, exists := subnetPort.Labels[servicecommon.LabelImageFetcher]; exists && value == "true" {
+			isVmSubnetPort = false
+			if labels == nil {
+				labels = &map[string]string{}
+			}
+			(*labels)[servicecommon.LabelImageFetcher] = "true"
+		}
+
+		nsxSubnetPortState, err := r.SubnetPortService.CreateOrUpdateSubnetPort(subnetPort, nsxSubnet, "", labels, isVmSubnetPort)
 		if err != nil {
 			r.StatusUpdater.UpdateFail(ctx, subnetPort, err, "", setSubnetPortReadyStatusFalse, r.SubnetPortService)
 			return common.ResultRequeue, err
diff --git a/pkg/nsx/services/common/types.go b/pkg/nsx/services/common/types.go
index 607bb5e4a..2b32f7e3b 100644
--- a/pkg/nsx/services/common/types.go
+++ b/pkg/nsx/services/common/types.go
@@ -60,6 +60,7 @@ const (
 	TagScopeVPCManagedBy               string = "nsx/managed-by"
 	AutoCreatedVPCTagValue             string = "nsx-op"
 	LabelDefaultSubnetSet              string = "nsxoperator.vmware.com/default-subnetset-for"
+	LabelImageFetcher                  string = "iaas.vmware.com/image-fetcher"
 	LabelDefaultVMSubnetSet            string = "VirtualMachine"
 	LabelDefaultPodSubnetSet           string = "Pod"
 	LabelLbIngressIpMode               string = "nsx.vmware.com/ingress-ip-mode"
diff --git a/pkg/nsx/services/subnetport/builder.go b/pkg/nsx/services/subnetport/builder.go
index eec4f9e8e..56c0cdee0 100644
--- a/pkg/nsx/services/subnetport/builder.go
+++ b/pkg/nsx/services/subnetport/builder.go
@@ -26,7 +26,7 @@ var (
 	String = common.String
 )
 
-func (service *SubnetPortService) buildSubnetPort(obj interface{}, nsxSubnet *model.VpcSubnet, contextID string, labelTags *map[string]string) (*model.VpcSubnetPort, error) {
+func (service *SubnetPortService) buildSubnetPort(obj interface{}, nsxSubnet *model.VpcSubnet, contextID string, labelTags *map[string]string, isVmSubnetPort bool) (*model.VpcSubnetPort, error) {
 	var objNamespace, appId, allocateAddresses string
 	objMeta := getObjectMeta(obj)
 	if objMeta == nil {
@@ -65,6 +65,27 @@ func (service *SubnetPortService) buildSubnetPort(obj interface{}, nsxSubnet *mo
 	}
 	namespace_uid := namespace.UID
 	tags := util.BuildBasicTags(getCluster(service), obj, namespace_uid)
+
+	// Filter tags based on the type of subnet port (VM or Pod).
+	// For VM subnet ports, we need to filter out tags with scope VMNamespaceUID and VMNamespace.
+	// For Pod subnet ports, we need to filter out tags with scope NamespaceUID and Namespace.
+	var tagsFiltered []model.Tag
+	for _, tag := range tags {
+		if isVmSubnetPort && *tag.Scope == common.TagScopeNamespaceUID {
+			continue
+		}
+		if isVmSubnetPort && *tag.Scope == common.TagScopeNamespace {
+			continue
+		}
+		if !isVmSubnetPort && *tag.Scope == common.TagScopeVMNamespaceUID {
+			continue
+		}
+		if !isVmSubnetPort && *tag.Scope == common.TagScopeVMNamespace {
+			continue
+		}
+		tagsFiltered = append(tagsFiltered, tag)
+	}
+
 	if labelTags != nil {
 		// Append Namespace labels in order as tags
 		labelKeys := make([]string, 0, len(*labelTags))
@@ -73,7 +94,7 @@ func (service *SubnetPortService) buildSubnetPort(obj interface{}, nsxSubnet *mo
 		}
 		sort.Strings(labelKeys)
 		for _, k := range labelKeys {
-			tags = append(tags, model.Tag{Scope: common.String(k), Tag: common.String((*labelTags)[k])})
+			tagsFiltered = append(tagsFiltered, model.Tag{Scope: common.String(k), Tag: common.String((*labelTags)[k])})
 		}
 	}
 	nsxSubnetPort := &model.VpcSubnetPort{
@@ -85,7 +106,7 @@ func (service *SubnetPortService) buildSubnetPort(obj interface{}, nsxSubnet *mo
 			TrafficTag:        common.Int64(0),
 			Type_:             String("STATIC"),
 		},
-		Tags:                   tags,
+		Tags:                   tagsFiltered,
 		Path:                   &nsxSubnetPortPath,
 		ParentPath:             nsxSubnet.Path,
 		ExternalAddressBinding: externalAddressBinding,
diff --git a/pkg/nsx/services/subnetport/builder_test.go b/pkg/nsx/services/subnetport/builder_test.go
index b826f226a..d42dba752 100644
--- a/pkg/nsx/services/subnetport/builder_test.go
+++ b/pkg/nsx/services/subnetport/builder_test.go
@@ -87,7 +87,7 @@ func TestBuildSubnetPort(t *testing.T) {
 						Tag:   common.String("1.0.0"),
 					},
 					{
-						Scope: common.String("nsx-op/vm_namespace"),
+						Scope: common.String("nsx-op/namespace"),
 						Tag:   common.String("fake_ns"),
 					},
 					{
@@ -184,7 +184,7 @@ func TestBuildSubnetPort(t *testing.T) {
 
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			observedPort, err := service.buildSubnetPort(tt.obj, tt.nsxSubnet, tt.contextID, tt.labelTags)
+			observedPort, err := service.buildSubnetPort(tt.obj, tt.nsxSubnet, tt.contextID, tt.labelTags, false)
 			assert.Equal(t, tt.expectedPort, observedPort)
 			assert.Equal(t, common.CompareResource(SubnetPortToComparable(tt.expectedPort), SubnetPortToComparable(observedPort)), false)
 			assert.Equal(t, tt.expectedError, err)
diff --git a/pkg/nsx/services/subnetport/subnetport.go b/pkg/nsx/services/subnetport/subnetport.go
index 181828955..01679380c 100644
--- a/pkg/nsx/services/subnetport/subnetport.go
+++ b/pkg/nsx/services/subnetport/subnetport.go
@@ -79,7 +79,7 @@ func InitializeSubnetPort(service servicecommon.Service) (*SubnetPortService, er
 	return subnetPortService, nil
 }
 
-func (service *SubnetPortService) CreateOrUpdateSubnetPort(obj interface{}, nsxSubnet *model.VpcSubnet, contextID string, tags *map[string]string) (*model.SegmentPortState, error) {
+func (service *SubnetPortService) CreateOrUpdateSubnetPort(obj interface{}, nsxSubnet *model.VpcSubnet, contextID string, tags *map[string]string, isVmSubnetPort bool) (*model.SegmentPortState, error) {
 	var uid string
 	switch o := obj.(type) {
 	case *v1alpha1.SubnetPort:
@@ -88,7 +88,7 @@ func (service *SubnetPortService) CreateOrUpdateSubnetPort(obj interface{}, nsxS
 		uid = string(o.UID)
 	}
 	log.Info("creating or updating subnetport", "nsxSubnetPort.Id", uid, "nsxSubnetPath", *nsxSubnet.Path)
-	nsxSubnetPort, err := service.buildSubnetPort(obj, nsxSubnet, contextID, tags)
+	nsxSubnetPort, err := service.buildSubnetPort(obj, nsxSubnet, contextID, tags, isVmSubnetPort)
 	if err != nil {
 		log.Error(err, "failed to build NSX subnet port", "nsxSubnetPort.Id", uid, "*nsxSubnet.Path", *nsxSubnet.Path, "contextID", contextID)
 		return nil, err
diff --git a/pkg/nsx/services/subnetport/subnetport_test.go b/pkg/nsx/services/subnetport/subnetport_test.go
index 204e5e081..78f45ae9a 100644
--- a/pkg/nsx/services/subnetport/subnetport_test.go
+++ b/pkg/nsx/services/subnetport/subnetport_test.go
@@ -311,7 +311,7 @@ func TestSubnetPortService_CreateOrUpdateSubnetPort(t *testing.T) {
 			if patches != nil {
 				defer patches.Reset()
 			}
-			_, err := service.CreateOrUpdateSubnetPort(subnetPortCR, nsxSubnet, "", nil)
+			_, err := service.CreateOrUpdateSubnetPort(subnetPortCR, nsxSubnet, "", nil, false)
 			if (err != nil) != tt.wantErr {
 				t.Errorf("CreateOrUpdateSubnetPort() error = %v, wantErr %v", err, tt.wantErr)
 			}
diff --git a/pkg/util/utils.go b/pkg/util/utils.go
index 73908c432..e0800ea55 100644
--- a/pkg/util/utils.go
+++ b/pkg/util/utils.go
@@ -453,7 +453,6 @@ func BuildBasicTags(cluster string, obj interface{}, namespaceID types.UID) []mo
 			Tag:   String(strings.Join(common.TagValueVersion, ".")),
 		},
 	}
-	isVmSubnetPort := false
 	switch i := obj.(type) {
 	case *v1alpha1.StaticRoute:
 		tags = append(tags, model.Tag{Scope: String(common.TagScopeNamespace), Tag: String(i.ObjectMeta.Namespace)})
@@ -470,8 +469,9 @@ func BuildBasicTags(cluster string, obj interface{}, namespaceID types.UID) []mo
 		tags = append(tags, model.Tag{Scope: String(common.TagScopeSubnetSetCRName), Tag: String(i.ObjectMeta.Name)})
 		tags = append(tags, model.Tag{Scope: String(common.TagScopeSubnetSetCRUID), Tag: String(string(i.UID))})
 	case *v1alpha1.SubnetPort:
+		tags = append(tags, model.Tag{Scope: String(common.TagScopeNamespace), Tag: String(i.ObjectMeta.Namespace)})
 		tags = append(tags, model.Tag{Scope: String(common.TagScopeVMNamespace), Tag: String(i.ObjectMeta.Namespace)})
-		isVmSubnetPort = true
+		tags = append(tags, model.Tag{Scope: String(common.TagScopeVMNamespaceUID), Tag: String(string(namespaceID))})
 		tags = append(tags, model.Tag{Scope: String(common.TagScopeSubnetPortCRName), Tag: String(i.ObjectMeta.Name)})
 		tags = append(tags, model.Tag{Scope: String(common.TagScopeSubnetPortCRUID), Tag: String(string(i.UID))})
 	case *v1.Pod:
@@ -493,12 +493,7 @@ func BuildBasicTags(cluster string, obj interface{}, namespaceID types.UID) []mo
 	}
 
 	if len(namespaceID) > 0 {
-		if isVmSubnetPort == true {
-			// In the NSX subnet port created for VM, the namespace uid tag is TagScopeVMNamespaceUID instead of TagScopeNamespaceUID.
-			tags = append(tags, model.Tag{Scope: String(common.TagScopeVMNamespaceUID), Tag: String(string(namespaceID))})
-		} else {
-			tags = append(tags, model.Tag{Scope: String(common.TagScopeNamespaceUID), Tag: String(string(namespaceID))})
-		}
+		tags = append(tags, model.Tag{Scope: String(common.TagScopeNamespaceUID), Tag: String(string(namespaceID))})
 	}
 	return tags
 }


Reviews:
user: login: heypnus
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-03-06T07:57:47Z
user: login: timdengyun
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-03-07T06:06:13Z
user: login: lxiaopei
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-03-08T01:44:11Z
user: login: zhengxiexie
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-03-08T05:51:50Z
user: login: zhengxiexie
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-03-08T06:23:55Z
user: login: zhengxiexie
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-03-08T06:24:04Z
user: login: zhengxiexie
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-03-08T06:24:26Z
user: login: zhengxiexie
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-03-13T05:40:46Z
user: login: zhengxiexie
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2024-03-13T06:35:08Z
user: login: lxiaopei
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-31T05:47:40Z
user: login: lxiaopei
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-31T05:57:58Z
user: login: lxiaopei
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-31T06:02:08Z
user: login: zhengxiexie
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-31T06:12:30Z
user: login: dantingl
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-03-31T06:13:20Z
user: login: zhengxiexie
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-31T06:15:30Z
user: login: zhengxiexie
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-03-31T06:31:16Z
user: login: lxiaopei
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-18T02:21:19Z
user: login: zhengxiexie
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-18T02:37:32Z
user: login: lxiaopei
body: LGTM
state: DISMISSED
author_association: CONTRIBUTOR
submitted_at: 2025-04-18T03:50:09Z
user: login: dantingl
state: COMMENTED
author_association: COLLABORATOR
submitted_at: 2025-04-18T08:12:33Z
user: login: zhengxiexie
state: COMMENTED
author_association: CONTRIBUTOR
submitted_at: 2025-04-21T02:56:12Z
user: login: dantingl
state: APPROVED
author_association: COLLABORATOR
submitted_at: 2025-04-21T09:10:23Z
user: login: lxiaopei
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-04-21T09:30:21Z

Review comments:
diff_hunk: @@ -68,14 +79,14 @@ func (service *SubnetPortService) buildSubnetPort(obj interface{}, nsxSubnetPath
 			TrafficTag:        common.Int64(0),
 			Type_:             String("STATIC"),
 		},
-		Tags:       tags,
+		Tags:       tagsFiltered,
 		Path:       &nsxSubnetPortPath,
 		ParentPath: &nsxSubnetPath,
 	}
 	if appId != "" {
 		nsxSubnetPort.Attachment.AppId = &appId
-		nsxSubnetPort.Attachment.ContextId = &contextID
 	}
+	nsxSubnetPort.Attachment.ContextId = &contextID
path: pkg/nsx/services/subnetport/builder.go
user: login: heypnus
body: I'm not sure whether the combo `ContextId != nil` and `AppId == nil` can work. Did you test it?
created_at: 2024-03-06T07:52:49Z
author_association: CONTRIBUTOR
diff_hunk: @@ -465,9 +464,12 @@ func BuildBasicTags(cluster string, obj interface{}, namespaceID types.UID) []mo
 		tags = append(tags, model.Tag{Scope: String(common.TagScopeSubnetSetCRUID), Tag: String(string(i.UID))})
 	case *v1alpha1.SubnetPort:
 		tags = append(tags, model.Tag{Scope: String(common.TagScopeVMNamespace), Tag: String(i.ObjectMeta.Namespace)})
-		isVmSubnetPort = true
 		tags = append(tags, model.Tag{Scope: String(common.TagScopeSubnetPortCRName), Tag: String(i.ObjectMeta.Name)})
 		tags = append(tags, model.Tag{Scope: String(common.TagScopeSubnetPortCRUID), Tag: String(string(i.UID))})
+		if len(namespaceID) > 0 {
+			tags = append(tags, model.Tag{Scope: String(common.TagScopeVMNamespaceUID), Tag: String(string(namespaceID))})
+			tags = append(tags, model.Tag{Scope: String(common.TagScopeNamespaceUID), Tag: String(string(namespaceID))})
path: pkg/util/utils.go
user: login: heypnus
body: Did you test that the security policy can select the port by `podSelector`?
created_at: 2024-03-06T07:55:46Z
author_association: CONTRIBUTOR
diff_hunk: @@ -68,14 +79,14 @@ func (service *SubnetPortService) buildSubnetPort(obj interface{}, nsxSubnetPath
 			TrafficTag:        common.Int64(0),
 			Type_:             String("STATIC"),
 		},
-		Tags:       tags,
+		Tags:       tagsFiltered,
 		Path:       &nsxSubnetPortPath,
 		ParentPath: &nsxSubnetPath,
 	}
 	if appId != "" {
 		nsxSubnetPort.Attachment.AppId = &appId
-		nsxSubnetPort.Attachment.ContextId = &contextID
 	}
+	nsxSubnetPort.Attachment.ContextId = &contextID
 	return nsxSubnetPort, nil
path: pkg/nsx/services/subnetport/builder.go
user: login: heypnus
body: I saw in your second screenshot of the PR, the port status is "Failed", what's the error message? And is it expected?
created_at: 2024-03-06T07:57:41Z
author_association: CONTRIBUTOR
diff_hunk: @@ -231,10 +231,6 @@ func TestBuildTargetTags(t *testing.T) {
 					Scope: &tagScopeNamespace,
 					Tag:   &tagValueNS,
 				},
-				{
path: pkg/nsx/services/securitypolicy/builder_test.go
user: login: timdengyun
body: why removed this tag?
created_at: 2024-03-07T06:05:54Z
author_association: CONTRIBUTOR
diff_hunk: @@ -300,10 +296,6 @@ func TestBuildPeerTags(t *testing.T) {
 					Scope: &tagScopeNamespace,
 					Tag:   &tagValueNS,
 				},
-				{
path: pkg/nsx/services/securitypolicy/builder_test.go
user: login: timdengyun
body: why removed this tag?
created_at: 2024-03-07T06:06:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -263,10 +262,6 @@ var (
 			Scope: &tagScopeNamespace,
 			Tag:   &tagValueNS,
 		},
-		{
-			Scope: &tagScopeNamespaceUID,
path: pkg/nsx/services/securitypolicy/firewall_test.go
user: login: timdengyun
body: why removed this tag?
created_at: 2024-03-07T06:06:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -96,7 +96,19 @@ func (r *SubnetPortReconciler) Reconcile(ctx context.Context, req ctrl.Request)
 			log.Error(err, "failed to get labels from virtualmachine", "subnetPort.Name", subnetPort.Name, "subnetPort.UID", subnetPort.UID)
 			return common.ResultRequeue, err
 		}
-		nsxSubnetPortState, err := r.SubnetPortService.CreateOrUpdateSubnetPort(subnetPort, nsxSubnetPath, "", labels)
+
+		isVmSubnetPort := true
+		if subnetPort.Labels[servicecommon.LabelImageFetcher] == "true" {
+			isVmSubnetPort = false
+			if labels == nil {
+				labels = &map[string]string{}
+			}
+			(*labels)[servicecommon.LabelImageFetcher] = "true"
+		}
+		// specified by user, or default to the node id of the VM the pod runs on
+		contextID := subnetPort.Annotations[servicecommon.AnnotationNodeID]
path: pkg/controllers/subnetport/subnetport_controller.go
user: login: lxiaopei
body: pls check the latest design doc for the annotation name, this should be host name, and we need to retrieve the TN id using the host name.
created_at: 2024-03-08T01:44:10Z
author_association: CONTRIBUTOR
diff_hunk: @@ -465,9 +464,12 @@ func BuildBasicTags(cluster string, obj interface{}, namespaceID types.UID) []mo
 		tags = append(tags, model.Tag{Scope: String(common.TagScopeSubnetSetCRUID), Tag: String(string(i.UID))})
 	case *v1alpha1.SubnetPort:
 		tags = append(tags, model.Tag{Scope: String(common.TagScopeVMNamespace), Tag: String(i.ObjectMeta.Namespace)})
-		isVmSubnetPort = true
 		tags = append(tags, model.Tag{Scope: String(common.TagScopeSubnetPortCRName), Tag: String(i.ObjectMeta.Name)})
 		tags = append(tags, model.Tag{Scope: String(common.TagScopeSubnetPortCRUID), Tag: String(string(i.UID))})
+		if len(namespaceID) > 0 {
+			tags = append(tags, model.Tag{Scope: String(common.TagScopeVMNamespaceUID), Tag: String(string(namespaceID))})
+			tags = append(tags, model.Tag{Scope: String(common.TagScopeNamespaceUID), Tag: String(string(namespaceID))})
path: pkg/util/utils.go
user: login: zhengxiexie
body: securitypolicy e2e passed, it should did.
created_at: 2024-03-08T05:51:50Z
author_association: CONTRIBUTOR
diff_hunk: @@ -231,10 +231,6 @@ func TestBuildTargetTags(t *testing.T) {
 					Scope: &tagScopeNamespace,
 					Tag:   &tagValueNS,
 				},
-				{
path: pkg/nsx/services/securitypolicy/builder_test.go
user: login: zhengxiexie
body: oh, refactored BuildBasicTags and made a bug here, fixed, Thanks~~
created_at: 2024-03-08T06:23:55Z
author_association: CONTRIBUTOR
diff_hunk: @@ -263,10 +262,6 @@ var (
 			Scope: &tagScopeNamespace,
 			Tag:   &tagValueNS,
 		},
-		{
-			Scope: &tagScopeNamespaceUID,
path: pkg/nsx/services/securitypolicy/firewall_test.go
user: login: zhengxiexie
body: ditto
created_at: 2024-03-08T06:24:04Z
author_association: CONTRIBUTOR
diff_hunk: @@ -300,10 +296,6 @@ func TestBuildPeerTags(t *testing.T) {
 					Scope: &tagScopeNamespace,
 					Tag:   &tagValueNS,
 				},
-				{
path: pkg/nsx/services/securitypolicy/builder_test.go
user: login: zhengxiexie
body: ditto
created_at: 2024-03-08T06:24:25Z
author_association: CONTRIBUTOR
diff_hunk: @@ -68,14 +79,14 @@ func (service *SubnetPortService) buildSubnetPort(obj interface{}, nsxSubnetPath
 			TrafficTag:        common.Int64(0),
 			Type_:             String("STATIC"),
 		},
-		Tags:       tags,
+		Tags:       tagsFiltered,
 		Path:       &nsxSubnetPortPath,
 		ParentPath: &nsxSubnetPath,
 	}
 	if appId != "" {
 		nsxSubnetPort.Attachment.AppId = &appId
-		nsxSubnetPort.Attachment.ContextId = &contextID
 	}
+	nsxSubnetPort.Attachment.ContextId = &contextID
 	return nsxSubnetPort, nil
path: pkg/nsx/services/subnetport/builder.go
user: login: zhengxiexie
body: screenshot updated.
created_at: 2024-03-13T05:40:45Z
author_association: CONTRIBUTOR
diff_hunk: @@ -68,14 +79,14 @@ func (service *SubnetPortService) buildSubnetPort(obj interface{}, nsxSubnetPath
 			TrafficTag:        common.Int64(0),
 			Type_:             String("STATIC"),
 		},
-		Tags:       tags,
+		Tags:       tagsFiltered,
 		Path:       &nsxSubnetPortPath,
 		ParentPath: &nsxSubnetPath,
 	}
 	if appId != "" {
 		nsxSubnetPort.Attachment.AppId = &appId
-		nsxSubnetPort.Attachment.ContextId = &contextID
 	}
+	nsxSubnetPort.Attachment.ContextId = &contextID
path: pkg/nsx/services/subnetport/builder.go
user: login: zhengxiexie
body: Yes, after hacking, it can work.
Before:
<img width="710" alt="image" src="https://github.com/vmware-tanzu/nsx-operator/assets/4385934/f46efecf-4955-4f84-97fb-3550baeb533d">
After:
<img width="655" alt="image" src="https://github.com/vmware-tanzu/nsx-operator/assets/4385934/cd703c45-8b51-46bc-917a-6d91a242a460">

created_at: 2024-03-13T06:35:08Z
author_association: CONTRIBUTOR
diff_hunk: @@ -60,6 +60,8 @@ const (
 	TagScopeVPCManagedBy               string = "nsx/managed-by"
 	AutoCreatedVPCTagValue             string = "nsx-op"
 	LabelDefaultSubnetSet              string = "nsxoperator.vmware.com/default-subnetset-for"
+	LabelImageFetcher                  string = "wcp.vmware.com/image-fetcher"
path: pkg/nsx/services/common/types.go
user: login: lxiaopei
body: now  changed to iaas.vmware.com/image-fetcher
created_at: 2025-03-31T05:47:39Z
author_association: CONTRIBUTOR
diff_hunk: @@ -118,7 +119,27 @@ func (r *SubnetPortReconciler) Reconcile(ctx context.Context, req ctrl.Request)
 			r.StatusUpdater.UpdateFail(ctx, subnetPort, err, fmt.Sprintf("Failed to get Subnet by path: %s", nsxSubnetPath), setSubnetPortReadyStatusFalse, r.SubnetPortService)
 			return common.ResultRequeue, err
 		}
-		nsxSubnetPortState, err := r.SubnetPortService.CreateOrUpdateSubnetPort(subnetPort, nsxSubnet, "", labels)
+
+		isVmSubnetPort := true
+		if subnetPort.Labels[servicecommon.LabelImageFetcher] == "true" {
path: pkg/controllers/subnetport/subnetport_controller.go
user: login: lxiaopei
body: change to if fetcherValue, ok := subnetPort.Labels[servicecommon.LabelImageFetcher]; ok { ... }
created_at: 2025-03-31T05:57:58Z
author_association: CONTRIBUTOR
diff_hunk: @@ -65,6 +65,18 @@ func (service *SubnetPortService) buildSubnetPort(obj interface{}, nsxSubnet *mo
 	}
 	namespace_uid := namespace.UID
 	tags := util.BuildBasicTags(getCluster(service), obj, namespace_uid)
+
+	var tagsFiltered []model.Tag
+	for _, tag := range tags {
+		if isVmSubnetPort && *tag.Scope == common.TagScopeNamespaceUID {
path: pkg/nsx/services/subnetport/builder.go
user: login: lxiaopei
body: in which case we will have isVMSubnetPort: true and it has "namespace_uid" tag?
created_at: 2025-03-31T06:02:07Z
author_association: CONTRIBUTOR
diff_hunk: @@ -60,6 +60,8 @@ const (
 	TagScopeVPCManagedBy               string = "nsx/managed-by"
 	AutoCreatedVPCTagValue             string = "nsx-op"
 	LabelDefaultSubnetSet              string = "nsxoperator.vmware.com/default-subnetset-for"
+	LabelImageFetcher                  string = "wcp.vmware.com/image-fetcher"
+	AnnotationHostName                 string = "kubernetes.io/hostname"
path: pkg/nsx/services/common/types.go
user: login: dantingl
body: Could you check whether WCP will have this annotation for CRX placement
created_at: 2025-03-31T06:10:17Z
author_association: COLLABORATOR
diff_hunk: @@ -60,6 +60,8 @@ const (
 	TagScopeVPCManagedBy               string = "nsx/managed-by"
 	AutoCreatedVPCTagValue             string = "nsx-op"
 	LabelDefaultSubnetSet              string = "nsxoperator.vmware.com/default-subnetset-for"
+	LabelImageFetcher                  string = "wcp.vmware.com/image-fetcher"
path: pkg/nsx/services/common/types.go
user: login: zhengxiexie
body: ok
created_at: 2025-03-31T06:12:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -118,7 +119,27 @@ func (r *SubnetPortReconciler) Reconcile(ctx context.Context, req ctrl.Request)
 			r.StatusUpdater.UpdateFail(ctx, subnetPort, err, fmt.Sprintf("Failed to get Subnet by path: %s", nsxSubnetPath), setSubnetPortReadyStatusFalse, r.SubnetPortService)
 			return common.ResultRequeue, err
 		}
-		nsxSubnetPortState, err := r.SubnetPortService.CreateOrUpdateSubnetPort(subnetPort, nsxSubnet, "", labels)
+
+		isVmSubnetPort := true
+		if subnetPort.Labels[servicecommon.LabelImageFetcher] == "true" {
path: pkg/controllers/subnetport/subnetport_controller.go
user: login: zhengxiexie
body: ok
created_at: 2025-03-31T06:15:30Z
author_association: CONTRIBUTOR
diff_hunk: @@ -65,6 +65,18 @@ func (service *SubnetPortService) buildSubnetPort(obj interface{}, nsxSubnet *mo
 	}
 	namespace_uid := namespace.UID
 	tags := util.BuildBasicTags(getCluster(service), obj, namespace_uid)
+
+	var tagsFiltered []model.Tag
+	for _, tag := range tags {
+		if isVmSubnetPort && *tag.Scope == common.TagScopeNamespaceUID {
path: pkg/nsx/services/subnetport/builder.go
user: login: zhengxiexie
body: I remove isVMSubnetPort in BuildBasicTags, and use filter outside of it,  and pass a argument to 
`func (service *SubnetPortService) CreateOrUpdateSubnetPort(obj interface{}, nsxSubnet *model.VpcSubnet, contextID string, tags *map[string]string, isVmSubnetPort bool) (*model.SegmentPortState, error) {
`
which is more reasonable
created_at: 2025-03-31T06:31:16Z
author_association: CONTRIBUTOR
diff_hunk: @@ -65,6 +65,18 @@ func (service *SubnetPortService) buildSubnetPort(obj interface{}, nsxSubnet *mo
 	}
 	namespace_uid := namespace.UID
 	tags := util.BuildBasicTags(getCluster(service), obj, namespace_uid)
+
+	var tagsFiltered []model.Tag
+	for _, tag := range tags {
+		if isVmSubnetPort && *tag.Scope == common.TagScopeNamespaceUID {
path: pkg/nsx/services/subnetport/builder.go
user: login: lxiaopei
body: for image-fetcher subnetport, it does not filter the vm_namespace tag.
created_at: 2025-04-18T02:21:19Z
author_association: CONTRIBUTOR
diff_hunk: @@ -65,6 +65,18 @@ func (service *SubnetPortService) buildSubnetPort(obj interface{}, nsxSubnet *mo
 	}
 	namespace_uid := namespace.UID
 	tags := util.BuildBasicTags(getCluster(service), obj, namespace_uid)
+
+	var tagsFiltered []model.Tag
+	for _, tag := range tags {
+		if isVmSubnetPort && *tag.Scope == common.TagScopeNamespaceUID {
path: pkg/nsx/services/subnetport/builder.go
user: login: zhengxiexie
body: fixed
created_at: 2025-04-18T02:37:27Z
author_association: CONTRIBUTOR
diff_hunk: @@ -65,6 +65,24 @@ func (service *SubnetPortService) buildSubnetPort(obj interface{}, nsxSubnet *mo
 	}
 	namespace_uid := namespace.UID
 	tags := util.BuildBasicTags(getCluster(service), obj, namespace_uid)
+
+	var tagsFiltered []model.Tag
+	for _, tag := range tags {
+		if isVmSubnetPort && *tag.Scope == common.TagScopeNamespaceUID {
path: pkg/nsx/services/subnetport/builder.go
user: login: dantingl
body: Can we add some comments for the logic here, there are a lot of blocks for different conditions.
created_at: 2025-04-18T08:12:15Z
author_association: COLLABORATOR
diff_hunk: @@ -65,6 +65,24 @@ func (service *SubnetPortService) buildSubnetPort(obj interface{}, nsxSubnet *mo
 	}
 	namespace_uid := namespace.UID
 	tags := util.BuildBasicTags(getCluster(service), obj, namespace_uid)
+
+	var tagsFiltered []model.Tag
+	for _, tag := range tags {
+		if isVmSubnetPort && *tag.Scope == common.TagScopeNamespaceUID {
path: pkg/nsx/services/subnetport/builder.go
user: login: zhengxiexie
body: fixed
created_at: 2025-04-21T02:56:12Z
author_association: CONTRIBUTOR

PR comments:
user: login: zhengxiexie
created_at: 2024-02-01T10:43:41Z
body: When creating a deny security policy
```
apiVersion: crd.nsx.vmware.com/v1alpha1
kind: SecurityPolicy
metadata:
  name: isolate-policy-1
spec:
  priority: 20
  appliedTo:
    - podSelector: {}
  rules:
    - direction: out
      action: drop
```

PodVM will fail to pull image
![image](https://github.com/user-attachments/assets/ecf9cbbf-41ac-4867-b9a2-57cf22adb022)

WCP adds a label "iaas.vmware.com/image-fetcher": "true" to CRXs vmware-system-image-d8818819-5520-4aed-b52d-7f756b89faa4, the label will reflect on nsx side
<img width="1087" alt="image" src="https://github.com/user-attachments/assets/cd6ec669-bf68-4609-989b-bdf6ac53e81b" />


Now create a higher priority security policy

```
apiVersion: crd.nsx.vmware.com/v1alpha1
kind: SecurityPolicy
metadata:
  name: allow-imagefetcher-policy
spec:
  priority: 19
  appliedTo:
    - podSelector:
        matchLabels:
          iaas.vmware.com/image-fetcher: "true"
  rules:
    - direction: out
      action: allow
```
The pod's image should succeed to pull.
<img width="687" alt="image" src="https://github.com/user-attachments/assets/90bd699d-38ea-4dd6-98e5-e7844c5cb03a" />

Ping from pod to NS/EW traffic should fail because of the deny security policy
<img width="437" alt="image" src="https://github.com/user-attachments/assets/7c9035f2-254f-4cb2-850f-75655a68a972" />
After delete the deny security policy, succeed
<img width="462" alt="image" src="https://github.com/user-attachments/assets/4869dc79-6169-4e2f-8597-ccb4e6d8b898" />



The above process doesn't effect VM image pulling
<img width="1737" alt="image" src="https://github.com/user-attachments/assets/5d073bbc-446b-4863-a495-5334fc2a0ddb" />
and traffic is also normal
<img width="670" alt="image" src="https://github.com/user-attachments/assets/680cd737-eb5d-4865-82e4-e09d80b5fbe6" />


author_association: CONTRIBUTOR
user: login: heypnus
created_at: 2024-02-19T07:15:05Z
body: Please do not write the internal url in the commit message
author_association: CONTRIBUTOR
user: login: zhengxiexie
created_at: 2024-02-23T02:17:30Z
body: > Please do not write the internal url in the commit message

ok
author_association: CONTRIBUTOR
user: login: zhengxiexie
created_at: 2024-03-08T08:16:13Z
body: /e2e
author_association: CONTRIBUTOR
user: login: timdengyun
created_at: 2024-03-17T09:06:25Z
body: /e2e
author_association: CONTRIBUTOR
user: login: timdengyun
created_at: 2024-03-17T09:33:15Z
body: /e2e
author_association: CONTRIBUTOR
user: login: zhengxiexie
created_at: 2024-03-26T05:21:53Z
body: /e2e
author_association: CONTRIBUTOR
user: login: zhengxiexie
created_at: 2024-06-25T03:49:32Z
body: /e2e
author_association: CONTRIBUTOR
user: login: codecov-commenter
created_at: 2025-03-31T04:05:28Z
body: ## [Codecov](https://app.codecov.io/gh/vmware-tanzu/nsx-operator/pull/510?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vmware-tanzu) Report
Attention: Patch coverage is `68.75000%` with `10 lines` in your changes missing coverage. Please review.
> Project coverage is 75.05%. Comparing base [(`7d1f760`)](https://app.codecov.io/gh/vmware-tanzu/nsx-operator/commit/7d1f760f36f7ce2811d8657de932eea9f3ceb348?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vmware-tanzu) to head [(`3e8de42`)](https://app.codecov.io/gh/vmware-tanzu/nsx-operator/commit/3e8de4279df6a1c8da1d02d197c820427646bdff?dropdown=coverage&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vmware-tanzu).
> Report is 4 commits behind head on main.

| [Files with missing lines](https://app.codecov.io/gh/vmware-tanzu/nsx-operator/pull/510?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vmware-tanzu) | Patch % | Lines |
|---|---|---|
| [...kg/controllers/subnetport/subnetport\_controller.go](https://app.codecov.io/gh/vmware-tanzu/nsx-operator/pull/510?src=pr&el=tree&filepath=pkg%2Fcontrollers%2Fsubnetport%2Fsubnetport_controller.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vmware-tanzu#diff-cGtnL2NvbnRyb2xsZXJzL3N1Ym5ldHBvcnQvc3VibmV0cG9ydF9jb250cm9sbGVyLmdv) | 25.00% | [5 Missing and 1 partial :warning: ](https://app.codecov.io/gh/vmware-tanzu/nsx-operator/pull/510?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vmware-tanzu) |
| [pkg/nsx/services/subnetport/builder.go](https://app.codecov.io/gh/vmware-tanzu/nsx-operator/pull/510?src=pr&el=tree&filepath=pkg%2Fnsx%2Fservices%2Fsubnetport%2Fbuilder.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vmware-tanzu#diff-cGtnL25zeC9zZXJ2aWNlcy9zdWJuZXRwb3J0L2J1aWxkZXIuZ28=) | 77.77% | [2 Missing and 2 partials :warning: ](https://app.codecov.io/gh/vmware-tanzu/nsx-operator/pull/510?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vmware-tanzu) |

<details><summary>Additional details and impacted files</summary>


[![Impacted file tree graph](https://app.codecov.io/gh/vmware-tanzu/nsx-operator/pull/510/graphs/tree.svg?width=650&height=150&src=pr&token=R0Q6IGC2PC&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vmware-tanzu)](https://app.codecov.io/gh/vmware-tanzu/nsx-operator/pull/510?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vmware-tanzu)

```diff
@@            Coverage Diff             @@
##             main     #510      +/-   ##
==========================================
+ Coverage   74.53%   75.05%   +0.52%     
==========================================
  Files         138      138              
  Lines       18771    18829      +58     
==========================================
+ Hits        13991    14133     +142     
+ Misses       3890     3806      -84     
  Partials      890      890              
```

| [Flag](https://app.codecov.io/gh/vmware-tanzu/nsx-operator/pull/510/flags?src=pr&el=flags&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vmware-tanzu) | Coverage Δ | |
|---|---|---|
| [unit-tests](https://app.codecov.io/gh/vmware-tanzu/nsx-operator/pull/510/flags?src=pr&el=flag&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vmware-tanzu) | `75.05% <68.75%> (+0.52%)` | :arrow_up: |

| [Files with missing lines](https://app.codecov.io/gh/vmware-tanzu/nsx-operator/pull/510?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vmware-tanzu) | Coverage Δ | |
|---|---|---|
| [pkg/controllers/pod/pod\_controller.go](https://app.codecov.io/gh/vmware-tanzu/nsx-operator/pull/510?src=pr&el=tree&filepath=pkg%2Fcontrollers%2Fpod%2Fpod_controller.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vmware-tanzu#diff-cGtnL2NvbnRyb2xsZXJzL3BvZC9wb2RfY29udHJvbGxlci5nbw==) | `70.31% <100.00%> (ø)` | |
| [pkg/nsx/services/common/types.go](https://app.codecov.io/gh/vmware-tanzu/nsx-operator/pull/510?src=pr&el=tree&filepath=pkg%2Fnsx%2Fservices%2Fcommon%2Ftypes.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vmware-tanzu#diff-cGtnL25zeC9zZXJ2aWNlcy9jb21tb24vdHlwZXMuZ28=) | `100.00% <ø> (ø)` | |
| [pkg/nsx/services/subnetport/subnetport.go](https://app.codecov.io/gh/vmware-tanzu/nsx-operator/pull/510?src=pr&el=tree&filepath=pkg%2Fnsx%2Fservices%2Fsubnetport%2Fsubnetport.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vmware-tanzu#diff-cGtnL25zeC9zZXJ2aWNlcy9zdWJuZXRwb3J0L3N1Ym5ldHBvcnQuZ28=) | `83.47% <100.00%> (ø)` | |
| [pkg/util/utils.go](https://app.codecov.io/gh/vmware-tanzu/nsx-operator/pull/510?src=pr&el=tree&filepath=pkg%2Futil%2Futils.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vmware-tanzu#diff-cGtnL3V0aWwvdXRpbHMuZ28=) | `87.78% <100.00%> (+0.98%)` | :arrow_up: |
| [pkg/nsx/services/subnetport/builder.go](https://app.codecov.io/gh/vmware-tanzu/nsx-operator/pull/510?src=pr&el=tree&filepath=pkg%2Fnsx%2Fservices%2Fsubnetport%2Fbuilder.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vmware-tanzu#diff-cGtnL25zeC9zZXJ2aWNlcy9zdWJuZXRwb3J0L2J1aWxkZXIuZ28=) | `82.87% <77.77%> (-1.10%)` | :arrow_down: |
| [...kg/controllers/subnetport/subnetport\_controller.go](https://app.codecov.io/gh/vmware-tanzu/nsx-operator/pull/510?src=pr&el=tree&filepath=pkg%2Fcontrollers%2Fsubnetport%2Fsubnetport_controller.go&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vmware-tanzu#diff-cGtnL2NvbnRyb2xsZXJzL3N1Ym5ldHBvcnQvc3VibmV0cG9ydF9jb250cm9sbGVyLmdv) | `73.49% <25.00%> (-0.69%)` | :arrow_down: |

... and [3 files with indirect coverage changes](https://app.codecov.io/gh/vmware-tanzu/nsx-operator/pull/510/indirect-changes?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=vmware-tanzu)

</details>
<details><summary> :rocket: New features to boost your workflow: </summary>

- :snowflake: [Test Analytics](https://docs.codecov.com/docs/test-analytics): Detect flaky tests, report on failures, and find test suite problems.
</details>
author_association: NONE
user: login: zhengxiexie
created_at: 2025-03-31T06:33:54Z
body: /e2e
author_association: CONTRIBUTOR
user: login: zhengxiexie
created_at: 2025-03-31T06:34:16Z
body: /e2e
author_association: CONTRIBUTOR
user: login: zhengxiexie
created_at: 2025-04-14T06:51:09Z
body: /e2e
author_association: CONTRIBUTOR
user: login: zhengxiexie
created_at: 2025-04-14T07:35:42Z
body: /e2e
author_association: CONTRIBUTOR
user: login: zhengxiexie
created_at: 2025-04-16T02:19:30Z
body: /e2e
author_association: CONTRIBUTOR
user: login: zhengxiexie
created_at: 2025-04-16T04:15:23Z
body: /e2e
author_association: CONTRIBUTOR
user: login: zhengxiexie
created_at: 2025-04-16T06:03:05Z
body: /e2e
author_association: CONTRIBUTOR
user: login: zhengxiexie
created_at: 2025-04-17T09:38:19Z
body: /e2e
author_association: CONTRIBUTOR
user: login: zhengxiexie
created_at: 2025-04-17T09:48:16Z
body: /e2e
author_association: CONTRIBUTOR
user: login: zhengxiexie
created_at: 2025-04-18T03:46:11Z
body: /e2e
author_association: CONTRIBUTOR
user: login: zhengxiexie
created_at: 2025-04-18T05:12:12Z
body: /e2e
author_association: CONTRIBUTOR
user: login: zhengxiexie
created_at: 2025-04-18T05:44:46Z
body: /e2e
author_association: CONTRIBUTOR
user: login: zhengxiexie
created_at: 2025-04-18T06:47:33Z
body: /e2e
author_association: CONTRIBUTOR
user: login: zhengxiexie
created_at: 2025-04-18T07:56:44Z
body: /e2e
author_association: CONTRIBUTOR
user: login: zhengxiexie
created_at: 2025-04-21T02:50:26Z
body: /e2e
author_association: CONTRIBUTOR