Skip to content

Commit 7b273b5

Browse files
authored
Update Subnet/SubnetSet API for DHCP changes (vmware-tanzu#878)
The PR supports DHCP changes in NSX subnet. Testing done: Create Subnet with DHCPServer/DHCPDeactivated mode and create a vm on it Create SubnetSet with DHCPServer/DHCPDeactivated mode and create a vm on it Create a Subnet with DHCPServer and create a vm on it, switch from DHCPServer to DHCPDeactivated Create a SubnetSet with DHCPServer and create a vm on it, switch from DHCPServer to DHCPDeactivated Signed-off-by: Yanjun Zhou <[email protected]>
1 parent 828b8d8 commit 7b273b5

File tree

15 files changed

+257
-46
lines changed

15 files changed

+257
-46
lines changed

go.sum

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,6 @@ github.com/vmware-tanzu/vm-operator/api v1.8.2/go.mod h1:vauVboD3sQxP+pb28TnI9wf
145145
github.com/vmware/govmomi v0.27.4 h1:5kY8TAkhB20lsjzrjE073eRb8+HixBI29PVMG5lxq6I=
146146
github.com/vmware/govmomi v0.27.4/go.mod h1:daTuJEcQosNMXYJOeku0qdBJP9SOLLWB3Mqz8THtv6o=
147147
github.com/vmware/vmw-guestinfo v0.0.0-20170707015358-25eff159a728/go.mod h1:x9oS4Wk2s2u4tS29nEaDLdzvuHdB19CvSGJjPgkZJNk=
148-
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
149-
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
150148
github.com/vmware/vsphere-automation-sdk-go/lib v0.7.0 h1:pT+oqJ8FD5eUBQkl+e7LZwwtbwPvW5kDyyGXvt66gOM=
151149
github.com/vmware/vsphere-automation-sdk-go/lib v0.7.0/go.mod h1:f3+6YVZpNcK2pYyiQ94BoHWmjMj9BnYav0vNFuTiDVM=
152150
github.com/vmware/vsphere-automation-sdk-go/runtime v0.7.0 h1:pSBxa9Agh6bgW8Hr0A1eQxuwnxGTnuAVox8iQb023hg=
@@ -155,6 +153,8 @@ github.com/vmware/vsphere-automation-sdk-go/services/nsxt v0.0.0-20241113023437-
155153
github.com/vmware/vsphere-automation-sdk-go/services/nsxt v0.0.0-20241113023437-5938c535c194/go.mod h1:M+J1qwzF4o7sAb/2VRu/edl1HLCdC++C4SNUrgiuGlQ=
156154
github.com/vmware/vsphere-automation-sdk-go/services/nsxt-mp v0.0.0-20241113023437-5938c535c194 h1:m0ZD9SXLwI4Q+nljYfmNrOpveUGud0wKefGVHkPJTW8=
157155
github.com/vmware/vsphere-automation-sdk-go/services/nsxt-mp v0.0.0-20241113023437-5938c535c194/go.mod h1:ugk9I4YM62SSAox57l5NAVBCRIkPQ1RNLb3URxyTADc=
156+
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
157+
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
158158
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
159159
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
160160
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=

pkg/controllers/common/utils_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ func TestAllocateSubnetFromSubnetSet(t *testing.T) {
120120
Return([]*model.VpcSubnet{})
121121
ssp.(*pkg_mock.MockSubnetServiceProvider).On("GenerateSubnetNSTags", mock.Anything)
122122
vsp.(*pkg_mock.MockVPCServiceProvider).On("ListVPCInfo", mock.Anything).Return([]servicecommon.VPCResourceInfo{{}})
123-
ssp.(*pkg_mock.MockSubnetServiceProvider).On("CreateOrUpdateSubnet", mock.Anything, mock.Anything, mock.Anything).Return(expectedSubnetPath, nil)
123+
ssp.(*pkg_mock.MockSubnetServiceProvider).On("CreateOrUpdateSubnet", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(expectedSubnetPath, nil)
124124
},
125125
expectedResult: expectedSubnetPath,
126126
},

pkg/controllers/subnet/subnet_controller.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,14 @@ func (r *SubnetReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctr
120120
}
121121
// Create or update the subnet in NSX
122122
if _, err := r.SubnetService.CreateOrUpdateSubnet(subnetCR, vpcInfoList[0], tags); err != nil {
123-
if errors.As(err, &nsxutil.ExceedTagsError{}) {
124-
r.StatusUpdater.UpdateFail(ctx, subnetCR, err, "Tags limit exceeded", setSubnetReadyStatusFalse)
125-
return ResultNormal, nil
123+
if err != nil {
124+
if errors.As(err, &nsxutil.ExceedTagsError{}) {
125+
r.StatusUpdater.UpdateFail(ctx, subnetCR, err, "Tags limit exceeded", setSubnetReadyStatusFalse)
126+
return ResultNormal, nil
127+
}
128+
r.StatusUpdater.UpdateFail(ctx, subnetCR, err, "Failed to create/update Subnet", setSubnetReadyStatusFalse)
129+
return ResultRequeue, err
126130
}
127-
r.StatusUpdater.UpdateFail(ctx, subnetCR, err, "Failed to create/update Subnet", setSubnetReadyStatusFalse)
128-
return ResultRequeue, err
129131
}
130132
// Update status
131133
if err := r.updateSubnetStatus(subnetCR); err != nil {
@@ -213,11 +215,15 @@ func (r *SubnetReconciler) updateSubnetStatus(obj *v1alpha1.Subnet) error {
213215

214216
func setSubnetReadyStatusTrue(client client.Client, ctx context.Context, obj client.Object, transitionTime metav1.Time, _ ...interface{}) {
215217
subnet := obj.(*v1alpha1.Subnet)
218+
dhcpMode := subnet.Spec.SubnetDHCPConfig.Mode
219+
if dhcpMode == "" {
220+
dhcpMode = v1alpha1.DHCPConfigMode(v1alpha1.DHCPConfigModeDeactivated)
221+
}
216222
newConditions := []v1alpha1.Condition{
217223
{
218224
Type: v1alpha1.Ready,
219225
Status: v1.ConditionTrue,
220-
Message: "NSX Subnet has been successfully created/updated",
226+
Message: fmt.Sprintf("NSX Subnet with %s has been successfully created/updated", dhcpMode),
221227
Reason: "SubnetReady",
222228
LastTransitionTime: transitionTime,
223229
},

pkg/controllers/subnetset/subnetset_controller.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,9 +111,9 @@ func (r *SubnetSetReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
111111
}
112112
}
113113

114-
// update SubnetSet tags if labels of namespace changed
115114
nsxSubnets := r.SubnetService.SubnetStore.GetByIndex(servicecommon.TagScopeSubnetSetCRUID, string(subnetsetCR.UID))
116115
if len(nsxSubnets) > 0 {
116+
// update SubnetSet tags if labels of namespace changed
117117
tags := r.SubnetService.GenerateSubnetNSTags(subnetsetCR)
118118
if tags == nil {
119119
log.Error(nil, "Failed to generate SubnetSet tags", "SubnetSet", req.NamespacedName)
@@ -125,8 +125,8 @@ func (r *SubnetSetReconciler) Reconcile(ctx context.Context, req ctrl.Request) (
125125
r.StatusUpdater.UpdateFail(ctx, subnetsetCR, err, "Exceed tags limit", setSubnetSetReadyStatusFalse)
126126
return ResultNormal, nil
127127
}
128-
if err := r.SubnetService.UpdateSubnetSetTags(subnetsetCR.Namespace, nsxSubnets, tags); err != nil {
129-
r.StatusUpdater.UpdateFail(ctx, subnetsetCR, err, "Failed to update SubnetSet tags", setSubnetSetReadyStatusFalse)
128+
if err := r.SubnetService.UpdateSubnetSet(subnetsetCR.Namespace, nsxSubnets, tags, string(subnetsetCR.Spec.SubnetDHCPConfig.Mode)); err != nil {
129+
r.StatusUpdater.UpdateFail(ctx, subnetsetCR, err, "Failed to update SubnetSet", setSubnetSetReadyStatusFalse)
130130
return ResultRequeue, nil
131131
}
132132
}

pkg/controllers/subnetset/subnetset_controller_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -145,8 +145,8 @@ func TestReconcile(t *testing.T) {
145145
},
146146
},
147147
{
148-
// return nil and not requeue when UpdateSubnetSetTags failed
149-
name: "Create a SubnetSet failed to UpdateSubnetSetTags",
148+
// return nil and requeue when UpdateSubnetSet failed
149+
name: "Create a SubnetSet failed to UpdateSubnetSet",
150150
expectRes: ResultRequeue,
151151
expectErrStr: "",
152152
patches: func(r *SubnetSetReconciler) *gomonkey.Patches {
@@ -226,8 +226,8 @@ func TestReconcile(t *testing.T) {
226226
return tags
227227
})
228228

229-
// UpdateSubnetSetTags
230-
patches.ApplyMethod(reflect.TypeOf(r.SubnetService), "UpdateSubnetSetTags", func(_ *subnet.SubnetService, ns string, vpcSubnets []*model.VpcSubnet, tags []model.Tag) error {
229+
// UpdateSubnetSet
230+
patches.ApplyMethod(reflect.TypeOf(r.SubnetService), "UpdateSubnetSet", func(_ *subnet.SubnetService, ns string, vpcSubnets []*model.VpcSubnet, tags []model.Tag, dhcpMode string) error {
231231
return nil
232232
})
233233
return patches

pkg/nsx/services/subnet/builder.go

Lines changed: 33 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package subnet
22

33
import (
44
"fmt"
5+
"strings"
56

67
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model"
78
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -53,35 +54,49 @@ func convertAccessMode(accessMode string) string {
5354
return accessMode
5455
}
5556

56-
func (service *SubnetService) buildSubnet(obj client.Object, tags []model.Tag) (*model.VpcSubnet, error) {
57+
func (service *SubnetService) buildSubnet(obj client.Object, tags []model.Tag, useLegacyAPI bool) (*model.VpcSubnet, error) {
5758
tags = append(service.buildBasicTags(obj), tags...)
5859
var nsxSubnet *model.VpcSubnet
5960
var staticIpAllocation bool
6061
switch o := obj.(type) {
6162
case *v1alpha1.Subnet:
62-
enableDhcp := (o.Spec.SubnetDHCPConfig.Mode != "" && o.Spec.SubnetDHCPConfig.Mode != v1alpha1.DHCPConfigMode(v1alpha1.DHCPConfigModeDeactivated))
63+
staticIpAllocation = (o.Spec.SubnetDHCPConfig.Mode == "" || o.Spec.SubnetDHCPConfig.Mode == v1alpha1.DHCPConfigMode(v1alpha1.DHCPConfigModeDeactivated))
6364
nsxSubnet = &model.VpcSubnet{
6465
Id: String(service.BuildSubnetID(o)),
6566
AccessMode: String(convertAccessMode(util.Capitalize(string(o.Spec.AccessMode)))),
6667
Ipv4SubnetSize: Int64(int64(o.Spec.IPv4SubnetSize)),
67-
DhcpConfig: service.buildDHCPConfig(enableDhcp),
6868
DisplayName: String(service.buildSubnetName(o)),
6969
}
70-
staticIpAllocation = !enableDhcp
70+
dhcpMode := string(o.Spec.SubnetDHCPConfig.Mode)
71+
if dhcpMode == "" {
72+
dhcpMode = v1alpha1.DHCPConfigModeDeactivated
73+
}
74+
if useLegacyAPI {
75+
nsxSubnet.DhcpConfig = service.buildDHCPConfig(dhcpMode != v1alpha1.DHCPConfigModeDeactivated)
76+
} else {
77+
nsxSubnet.SubnetDhcpConfig = service.buildSubnetDHCPConfig(dhcpMode)
78+
}
7179
nsxSubnet.IpAddresses = o.Spec.IPAddresses
7280
case *v1alpha1.SubnetSet:
7381
// The index is a random string with the length of 8 chars. It is the first 8 chars of the hash
7482
// value on a random UUID string.
75-
enableDhcp := (o.Spec.SubnetDHCPConfig.Mode != "" && o.Spec.SubnetDHCPConfig.Mode != v1alpha1.DHCPConfigMode(v1alpha1.DHCPConfigModeDeactivated))
83+
staticIpAllocation = (o.Spec.SubnetDHCPConfig.Mode == "" || o.Spec.SubnetDHCPConfig.Mode == v1alpha1.DHCPConfigMode(v1alpha1.DHCPConfigModeDeactivated))
7684
index := util.GetRandomIndexString()
7785
nsxSubnet = &model.VpcSubnet{
7886
Id: String(service.buildSubnetSetID(o, index)),
7987
AccessMode: String(convertAccessMode(util.Capitalize(string(o.Spec.AccessMode)))),
8088
Ipv4SubnetSize: Int64(int64(o.Spec.IPv4SubnetSize)),
81-
DhcpConfig: service.buildDHCPConfig(enableDhcp),
8289
DisplayName: String(service.buildSubnetSetName(o, index)),
8390
}
84-
staticIpAllocation = !enableDhcp
91+
dhcpMode := string(o.Spec.SubnetDHCPConfig.Mode)
92+
if dhcpMode == "" {
93+
dhcpMode = v1alpha1.DHCPConfigModeDeactivated
94+
}
95+
if useLegacyAPI {
96+
nsxSubnet.DhcpConfig = service.buildDHCPConfig(dhcpMode != v1alpha1.DHCPConfigModeDeactivated)
97+
} else {
98+
nsxSubnet.SubnetDhcpConfig = service.buildSubnetDHCPConfig(dhcpMode)
99+
}
85100
default:
86101
return nil, SubnetTypeError
87102
}
@@ -108,6 +123,17 @@ func (service *SubnetService) buildDHCPConfig(enableDHCP bool) *model.VpcSubnetD
108123
return dhcpConfig
109124
}
110125

126+
func (service *SubnetService) buildSubnetDHCPConfig(mode string) *model.SubnetDhcpConfig {
127+
// Trasfer DHCPDeactivated to DHCP_DEACTIVATED
128+
nsxMode := strings.ToUpper(mode)
129+
nsxMode = nsxMode[:4] + "_" + nsxMode[4:]
130+
131+
subnetDhcpConfig := &model.SubnetDhcpConfig{
132+
Mode: &nsxMode,
133+
}
134+
return subnetDhcpConfig
135+
}
136+
111137
func (service *SubnetService) buildBasicTags(obj client.Object) []model.Tag {
112138
return util.BuildBasicTags(getCluster(service), obj, "")
113139
}

pkg/nsx/services/subnet/builder_test.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,15 @@ package subnet
33
import (
44
"testing"
55

6+
"github.com/golang/mock/gomock"
67
"github.com/stretchr/testify/assert"
8+
"github.com/vmware/vsphere-automation-sdk-go/services/nsxt/model"
79
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
10+
"k8s.io/client-go/tools/cache"
811

912
"github.com/vmware-tanzu/nsx-operator/pkg/apis/vpc/v1alpha1"
1013
"github.com/vmware-tanzu/nsx-operator/pkg/config"
14+
mock_client "github.com/vmware-tanzu/nsx-operator/pkg/mock/controller-runtime/client"
1115
"github.com/vmware-tanzu/nsx-operator/pkg/nsx/services/common"
1216
)
1317

@@ -60,3 +64,47 @@ func TestBuildSubnetSetName(t *testing.T) {
6064
expId := "pod-default_28e85c0b-21e4-4cab-b1c3-597639dfe752_0c5d588b"
6165
assert.Equal(t, expId, id)
6266
}
67+
68+
func TestBuildSubnetForSubnetSet(t *testing.T) {
69+
mockCtl := gomock.NewController(t)
70+
k8sClient := mock_client.NewMockClient(mockCtl)
71+
defer mockCtl.Finish()
72+
service := &SubnetService{
73+
Service: common.Service{
74+
Client: k8sClient,
75+
NSXConfig: &config.NSXOperatorConfig{
76+
CoeConfig: &config.CoeConfig{
77+
Cluster: "k8scl-one:test",
78+
},
79+
},
80+
},
81+
SubnetStore: &SubnetStore{
82+
ResourceStore: common.ResourceStore{
83+
Indexer: cache.NewIndexer(keyFunc, cache.Indexers{
84+
common.TagScopeSubnetCRUID: subnetIndexFunc,
85+
common.TagScopeSubnetSetCRUID: subnetSetIndexFunc,
86+
common.TagScopeVMNamespace: subnetIndexVMNamespaceFunc,
87+
common.TagScopeNamespace: subnetIndexNamespaceFunc,
88+
}),
89+
BindingType: model.VpcSubnetBindingType(),
90+
},
91+
},
92+
}
93+
tags := []model.Tag{
94+
{
95+
Scope: common.String("nsx-op/namespace"),
96+
Tag: common.String("ns-1"),
97+
},
98+
}
99+
subnetSet := &v1alpha1.SubnetSet{
100+
ObjectMeta: v1.ObjectMeta{
101+
Name: "subnetset-1",
102+
Namespace: "ns-1",
103+
},
104+
}
105+
subnet, err := service.buildSubnet(subnetSet, tags, true)
106+
assert.Nil(t, err)
107+
assert.Equal(t, false, *subnet.DhcpConfig.EnableDhcp)
108+
assert.Nil(t, subnet.SubnetDhcpConfig)
109+
assert.Equal(t, true, *subnet.AdvancedConfig.StaticIpAllocation.Enabled)
110+
}

pkg/nsx/services/subnet/compare.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,12 @@ func (subnet *Subnet) Key() string {
1818
}
1919

2020
func (subnet *Subnet) Value() data.DataValue {
21-
// IPv4SubnetSize/AccessMode/IPAddresses/DHCPConfig are immutable field,
22-
// Only changes of tags are considered as changed.
21+
// IPv4SubnetSize/AccessMode/IPAddresses are immutable field,
22+
// Changes of tags and subnetDHCPConfig are considered as changed.
2323
// TODO AccessMode may also need to be compared in future.
2424
s := &Subnet{
25-
Tags: subnet.Tags,
25+
Tags: subnet.Tags,
26+
SubnetDhcpConfig: subnet.SubnetDhcpConfig,
2627
}
2728
dataValue, _ := (*model.VpcSubnet)(s).GetDataValue__()
2829
return dataValue

pkg/nsx/services/subnet/subnet.go

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,14 @@ var (
3030
ResourceTypeSubnet = common.ResourceTypeSubnet
3131
NewConverter = common.NewConverter
3232
// Default static ip-pool under Subnet.
33-
SubnetTypeError = errors.New("unsupported type")
33+
SubnetTypeError = errors.New("unsupported type")
34+
ErrorCodeUnrecognizedField = int64(287)
3435
)
3536

3637
type SubnetService struct {
3738
common.Service
38-
SubnetStore *SubnetStore
39+
SubnetStore *SubnetStore
40+
useLegacyAPI bool
3941
}
4042

4143
// SubnetParameters stores parameters to CRUD Subnet object
@@ -81,9 +83,22 @@ func InitializeSubnetService(service common.Service) (*SubnetService, error) {
8183
return subnetService, nil
8284
}
8385

84-
func (service *SubnetService) CreateOrUpdateSubnet(obj client.Object, vpcInfo common.VPCResourceInfo, tags []model.Tag) (string, error) {
86+
func (service *SubnetService) CreateOrUpdateSubnet(obj client.Object, vpcInfo common.VPCResourceInfo, tags []model.Tag) (subnetPath string, err error) {
87+
if subnetPath, err = service.createOrUpdateSubnetWithAPI(obj, vpcInfo, tags, service.useLegacyAPI); err != nil {
88+
if nsxErr, ok := err.(*nsxutil.NSXApiError); ok {
89+
if *nsxErr.ErrorCode == ErrorCodeUnrecognizedField {
90+
log.Info("NSX does not support subnet_dhcp_config, using old API", "error", err)
91+
service.useLegacyAPI = true
92+
subnetPath, err = service.createOrUpdateSubnetWithAPI(obj, vpcInfo, tags, service.useLegacyAPI)
93+
}
94+
}
95+
}
96+
return subnetPath, err
97+
}
98+
99+
func (service *SubnetService) createOrUpdateSubnetWithAPI(obj client.Object, vpcInfo common.VPCResourceInfo, tags []model.Tag, useLegacyAPI bool) (string, error) {
85100
uid := string(obj.GetUID())
86-
nsxSubnet, err := service.buildSubnet(obj, tags)
101+
nsxSubnet, err := service.buildSubnet(obj, tags, useLegacyAPI)
87102
if err != nil {
88103
log.Error(err, "Failed to build Subnet")
89104
return "", err
@@ -97,9 +112,13 @@ func (service *SubnetService) CreateOrUpdateSubnet(obj client.Object, vpcInfo co
97112
} else {
98113
changed = common.CompareResource(SubnetToComparable(existingSubnet), SubnetToComparable(nsxSubnet))
99114
if changed {
100-
// Only tags are expected to be updated
115+
// Only tags and dhcp are expected to be updated
101116
// inherit other fields from the existing Subnet
102117
existingSubnet.Tags = nsxSubnet.Tags
118+
if existingSubnet.SubnetDhcpConfig != nil {
119+
existingSubnet.SubnetDhcpConfig = nsxSubnet.SubnetDhcpConfig
120+
existingSubnet.AdvancedConfig.StaticIpAllocation.Enabled = nsxSubnet.AdvancedConfig.StaticIpAllocation.Enabled
121+
}
103122
nsxSubnet = existingSubnet
104123
}
105124
}
@@ -388,11 +407,15 @@ func (service *SubnetService) GenerateSubnetNSTags(obj client.Object) []model.Ta
388407
return tags
389408
}
390409

391-
func (service *SubnetService) UpdateSubnetSetTags(ns string, vpcSubnets []*model.VpcSubnet, tags []model.Tag) error {
410+
func (service *SubnetService) UpdateSubnetSet(ns string, vpcSubnets []*model.VpcSubnet, tags []model.Tag, dhcpMode string) error {
411+
if dhcpMode == "" {
412+
dhcpMode = v1alpha1.DHCPConfigModeDeactivated
413+
}
414+
staticIpAllocation := (dhcpMode == v1alpha1.DHCPConfigModeDeactivated)
392415
for i, vpcSubnet := range vpcSubnets {
393416
subnetSet := &v1alpha1.SubnetSet{}
394417
var name string
395-
418+
// Generate new Subnet tags
396419
matchNamespace := false
397420
for _, t := range vpcSubnets[i].Tags {
398421
tag := t
@@ -417,12 +440,30 @@ func (service *SubnetService) UpdateSubnetSetTags(ns string, vpcSubnets []*model
417440
return fmt.Errorf("failed to get SubnetSet %s in Namespace %s: %w", name, ns, err)
418441
}
419442
newTags := append(service.buildBasicTags(subnetSet), tags...)
420-
changed := common.CompareResource(SubnetToComparable(vpcSubnets[i]), SubnetToComparable(&model.VpcSubnet{Tags: newTags}))
443+
444+
var updatedSubnet *model.VpcSubnet
445+
if vpcSubnets[i].SubnetDhcpConfig == nil {
446+
updatedSubnet = &model.VpcSubnet{
447+
Tags: newTags,
448+
}
449+
} else {
450+
updatedSubnet = &model.VpcSubnet{
451+
Tags: newTags,
452+
SubnetDhcpConfig: service.buildSubnetDHCPConfig(dhcpMode),
453+
}
454+
}
455+
changed := common.CompareResource(SubnetToComparable(vpcSubnets[i]), SubnetToComparable(updatedSubnet))
421456
if !changed {
422-
log.Info("NSX Subnet tags unchanged, skipping update", "subnet", *vpcSubnet.Id)
457+
log.Info("NSX Subnet unchanged, skipping update", "Subnet", *vpcSubnet.Id)
423458
continue
424459
}
460+
425461
vpcSubnets[i].Tags = newTags
462+
// Update the SubnetSet DHCP Config
463+
if vpcSubnets[i].SubnetDhcpConfig != nil {
464+
vpcSubnets[i].SubnetDhcpConfig = service.buildSubnetDHCPConfig(dhcpMode)
465+
vpcSubnets[i].AdvancedConfig.StaticIpAllocation.Enabled = &staticIpAllocation
466+
}
426467

427468
vpcInfo, err := common.ParseVPCResourcePath(*vpcSubnets[i].Path)
428469
if err != nil {
@@ -432,7 +473,7 @@ func (service *SubnetService) UpdateSubnetSetTags(ns string, vpcSubnets []*model
432473
if _, err := service.createOrUpdateSubnet(subnetSet, vpcSubnets[i], &vpcInfo); err != nil {
433474
return fmt.Errorf("failed to update Subnet %s in SubnetSet %s: %w", *vpcSubnet.Id, subnetSet.Name, err)
434475
}
435-
log.Info("Successfully updated SubnetSet tags", "subnetSet", subnetSet, "Subnet", *vpcSubnet.Id)
476+
log.Info("Successfully updated SubnetSet", "subnetSet", subnetSet, "Subnet", *vpcSubnet.Id)
436477
}
437478
return nil
438479
}

0 commit comments

Comments
 (0)