Skip to content

Commit c970d07

Browse files
authored
Create NNC scoped client and isolate ipampoolmonitor and NNC reconciler (#1006)
* create nodenetworkconfig client Signed-off-by: Evan Baker <[email protected]> * add envnodename to config Signed-off-by: Evan Baker <[email protected]> * rewrite and fully test nnc to nc conversion Signed-off-by: Evan Baker <[email protected]> * use nnc clients to separate reconciler and ipampoolmonitor Signed-off-by: Evan Baker <[email protected]> * inline reconciler event filters Signed-off-by: Evan Baker <[email protected]> * delint Signed-off-by: Evan Baker <[email protected]> * test env config Signed-off-by: Evan Baker <[email protected]> * wrap errs Signed-off-by: Evan Baker <[email protected]> * test reconciler Signed-off-by: Evan Baker <[email protected]> * address review comments Signed-off-by: Evan Baker <[email protected]> * rebase cleanup Signed-off-by: Evan Baker <[email protected]> * fix test Signed-off-by: Evan Baker <[email protected]> * address review feedback Signed-off-by: Evan Baker <[email protected]>
1 parent 779e965 commit c970d07

28 files changed

+910
-1704
lines changed

cns/configuration/env.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package configuration
2+
3+
import (
4+
"os"
5+
6+
"github.com/pkg/errors"
7+
)
8+
9+
const (
10+
// EnvNodeName is the NODENAME env var string key.
11+
EnvNodeName = "NODENAME"
12+
)
13+
14+
// ErrNodeNameUnset indicates the the $EnvNodeName variable is unset in the environment.
15+
var ErrNodeNameUnset = errors.Errorf("must declare %s environment variable", EnvNodeName)
16+
17+
// NodeName checks the environment variables for the NODENAME and returns it or an error if unset.
18+
func NodeName() (string, error) {
19+
nodeName := os.Getenv(EnvNodeName)
20+
if nodeName == "" {
21+
return "", ErrNodeNameUnset
22+
}
23+
return nodeName, nil
24+
}

cns/configuration/env_test.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package configuration
2+
3+
import (
4+
"os"
5+
"testing"
6+
7+
"github.com/stretchr/testify/assert"
8+
"github.com/stretchr/testify/require"
9+
)
10+
11+
func TestNodeName(t *testing.T) {
12+
_, err := NodeName()
13+
require.Error(t, err)
14+
require.ErrorIs(t, err, ErrNodeNameUnset)
15+
os.Setenv(EnvNodeName, "test")
16+
name, err := NodeName()
17+
assert.NoError(t, err)
18+
assert.Equal(t, "test", name)
19+
}

cns/fakes/requestcontrollerfake.go

Lines changed: 14 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,20 @@ import (
88
"net"
99

1010
"github.com/Azure/azure-container-networking/cns"
11-
"github.com/Azure/azure-container-networking/cns/singletenantcontroller"
1211
"github.com/Azure/azure-container-networking/crd/nodenetworkconfig/api/v1alpha"
1312
"github.com/google/uuid"
1413
)
1514

16-
var _ singletenantcontroller.RequestController = (*RequestControllerFake)(nil)
17-
1815
type RequestControllerFake struct {
19-
fakecns *HTTPServiceFake
20-
cachedCRD v1alpha.NodeNetworkConfig
21-
ip net.IP
16+
cnscli *HTTPServiceFake
17+
NNC *v1alpha.NodeNetworkConfig
18+
ip net.IP
2219
}
2320

2421
func NewRequestControllerFake(cnsService *HTTPServiceFake, scalar v1alpha.Scaler, subnetAddressSpace string, numberOfIPConfigs int) *RequestControllerFake {
2522
rc := &RequestControllerFake{
26-
fakecns: cnsService,
27-
cachedCRD: v1alpha.NodeNetworkConfig{
23+
cnscli: cnsService,
24+
NNC: &v1alpha.NodeNetworkConfig{
2825
Spec: v1alpha.NodeNetworkConfigSpec{},
2926
Status: v1alpha.NodeNetworkConfigStatus{
3027
Scaler: scalar,
@@ -40,7 +37,7 @@ func NewRequestControllerFake(cnsService *HTTPServiceFake, scalar v1alpha.Scaler
4037
rc.ip, _, _ = net.ParseCIDR(subnetAddressSpace)
4138

4239
rc.CarveIPConfigsAndAddToStatusAndCNS(numberOfIPConfigs)
43-
rc.cachedCRD.Spec.RequestedIPCount = int64(numberOfIPConfigs)
40+
rc.NNC.Spec.RequestedIPCount = int64(numberOfIPConfigs)
4441

4542
return rc
4643
}
@@ -53,7 +50,7 @@ func (rc *RequestControllerFake) CarveIPConfigsAndAddToStatusAndCNS(numberOfIPCo
5350
Name: uuid.New().String(),
5451
IP: rc.ip.String(),
5552
}
56-
rc.cachedCRD.Status.NetworkContainers[0].IPAssignments = append(rc.cachedCRD.Status.NetworkContainers[0].IPAssignments, ipconfigCRD)
53+
rc.NNC.Status.NetworkContainers[0].IPAssignments = append(rc.NNC.Status.NetworkContainers[0].IPAssignments, ipconfigCRD)
5754

5855
ipconfigCNS := cns.IPConfigurationStatus{
5956
ID: ipconfigCRD.Name,
@@ -65,7 +62,7 @@ func (rc *RequestControllerFake) CarveIPConfigsAndAddToStatusAndCNS(numberOfIPCo
6562
incrementIP(rc.ip)
6663
}
6764

68-
rc.fakecns.IPStateManager.AddIPConfigs(cnsIPConfigs)
65+
rc.cnscli.IPStateManager.AddIPConfigs(cnsIPConfigs)
6966

7067
return cnsIPConfigs
7168
}
@@ -82,17 +79,12 @@ func (rc *RequestControllerFake) IsStarted() bool {
8279
return true
8380
}
8481

85-
func (rc *RequestControllerFake) UpdateCRDSpec(_ context.Context, desiredSpec v1alpha.NodeNetworkConfigSpec) error {
86-
rc.cachedCRD.Spec = desiredSpec
87-
return nil
88-
}
89-
9082
func remove(slice []v1alpha.IPAssignment, s int) []v1alpha.IPAssignment {
9183
return append(slice[:s], slice[s+1:]...)
9284
}
9385

9486
func (rc *RequestControllerFake) Reconcile(removePendingReleaseIPs bool) error {
95-
diff := int(rc.cachedCRD.Spec.RequestedIPCount) - len(rc.fakecns.GetPodIPConfigState())
87+
diff := int(rc.NNC.Spec.RequestedIPCount) - len(rc.cnscli.GetPodIPConfigState())
9688

9789
if diff > 0 {
9890
// carve the difference of test IPs and add them to CNS, assume dnc has populated the CRD status
@@ -101,28 +93,28 @@ func (rc *RequestControllerFake) Reconcile(removePendingReleaseIPs bool) error {
10193
// Assume DNC has removed the IPConfigs from the status
10294

10395
// mimic DNC removing IPConfigs from the CRD
104-
for _, notInUseIPConfigName := range rc.cachedCRD.Spec.IPsNotInUse {
96+
for _, notInUseIPConfigName := range rc.NNC.Spec.IPsNotInUse {
10597

10698
// remove ipconfig from status
10799
index := 0
108-
for _, ipconfig := range rc.cachedCRD.Status.NetworkContainers[0].IPAssignments {
100+
for _, ipconfig := range rc.NNC.Status.NetworkContainers[0].IPAssignments {
109101
if notInUseIPConfigName == ipconfig.Name {
110102
break
111103
}
112104
index++
113105
}
114-
rc.cachedCRD.Status.NetworkContainers[0].IPAssignments = remove(rc.cachedCRD.Status.NetworkContainers[0].IPAssignments, index)
106+
rc.NNC.Status.NetworkContainers[0].IPAssignments = remove(rc.NNC.Status.NetworkContainers[0].IPAssignments, index)
115107

116108
}
117109
}
118110

119111
// remove ipconfig from CNS
120112
if removePendingReleaseIPs {
121-
rc.fakecns.IPStateManager.RemovePendingReleaseIPConfigs(rc.cachedCRD.Spec.IPsNotInUse)
113+
rc.cnscli.IPStateManager.RemovePendingReleaseIPConfigs(rc.NNC.Spec.IPsNotInUse)
122114
}
123115

124116
// update
125-
rc.fakecns.PoolMonitor.Update(rc.cachedCRD.Status.Scaler, rc.cachedCRD.Spec)
117+
rc.cnscli.PoolMonitor.Update(rc.NNC.Status.Scaler, rc.NNC.Spec)
126118

127119
return nil
128120
}

cns/ipampoolmonitor/ipampoolmonitor.go

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,28 +9,31 @@ import (
99
"github.com/Azure/azure-container-networking/cns"
1010
"github.com/Azure/azure-container-networking/cns/logger"
1111
"github.com/Azure/azure-container-networking/cns/metric"
12-
"github.com/Azure/azure-container-networking/cns/singletenantcontroller"
1312
"github.com/Azure/azure-container-networking/crd/nodenetworkconfig/api/v1alpha"
1413
)
1514

1615
const defaultMaxIPCount = int64(250)
1716

17+
type nodeNetworkConfigSpecUpdater interface {
18+
UpdateSpec(context.Context, *v1alpha.NodeNetworkConfigSpec) (*v1alpha.NodeNetworkConfig, error)
19+
}
20+
1821
type CNSIPAMPoolMonitor struct {
1922
MaximumFreeIps int64
2023
MinimumFreeIps int64
2124
cachedNNC v1alpha.NodeNetworkConfig
2225
httpService cns.HTTPService
2326
mu sync.RWMutex
24-
rc singletenantcontroller.RequestController
2527
scalarUnits v1alpha.Scaler
2628
updatingIpsNotInUseCount int
29+
nnccli nodeNetworkConfigSpecUpdater
2730
}
2831

29-
func NewCNSIPAMPoolMonitor(httpService cns.HTTPService, rc singletenantcontroller.RequestController) *CNSIPAMPoolMonitor {
32+
func NewCNSIPAMPoolMonitor(httpService cns.HTTPService, nnccli nodeNetworkConfigSpecUpdater) *CNSIPAMPoolMonitor {
3033
logger.Printf("NewCNSIPAMPoolMonitor: Create IPAM Pool Monitor")
3134
return &CNSIPAMPoolMonitor{
3235
httpService: httpService,
33-
rc: rc,
36+
nnccli: nnccli,
3437
}
3538
}
3639

@@ -135,7 +138,7 @@ func (pm *CNSIPAMPoolMonitor) increasePoolSize(ctx context.Context) error {
135138

136139
logger.Printf("[ipam-pool-monitor] Increasing pool size, Current Pool Size: %v, Updated Requested IP Count: %v, Pods with IP's:%v, ToBeDeleted Count: %v", len(pm.httpService.GetPodIPConfigState()), tempNNCSpec.RequestedIPCount, len(pm.httpService.GetAllocatedIPConfigs()), len(tempNNCSpec.IPsNotInUse))
137140

138-
if err := pm.rc.UpdateCRDSpec(ctx, tempNNCSpec); err != nil {
141+
if _, err := pm.nnccli.UpdateSpec(ctx, &tempNNCSpec); err != nil {
139142
// caller will retry to update the CRD again
140143
return err
141144
}
@@ -204,7 +207,7 @@ func (pm *CNSIPAMPoolMonitor) decreasePoolSize(ctx context.Context, existingPend
204207
tempNNCSpec.RequestedIPCount -= int64(len(pendingIPAddresses))
205208
logger.Printf("[ipam-pool-monitor] Decreasing pool size, Current Pool Size: %v, Requested IP Count: %v, Pods with IP's: %v, ToBeDeleted Count: %v", len(pm.httpService.GetPodIPConfigState()), tempNNCSpec.RequestedIPCount, len(pm.httpService.GetAllocatedIPConfigs()), len(tempNNCSpec.IPsNotInUse))
206209

207-
err := pm.rc.UpdateCRDSpec(ctx, tempNNCSpec)
210+
_, err := pm.nnccli.UpdateSpec(ctx, &tempNNCSpec)
208211
if err != nil {
209212
// caller will retry to update the CRD again
210213
return err
@@ -232,7 +235,7 @@ func (pm *CNSIPAMPoolMonitor) cleanPendingRelease(ctx context.Context) error {
232235

233236
tempNNCSpec := pm.createNNCSpecForCRD()
234237

235-
err := pm.rc.UpdateCRDSpec(ctx, tempNNCSpec)
238+
_, err := pm.nnccli.UpdateSpec(ctx, &tempNNCSpec)
236239
if err != nil {
237240
// caller will retry to update the CRD again
238241
return err

cns/ipampoolmonitor/ipampoolmonitor_test.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@ import (
1010
"github.com/Azure/azure-container-networking/crd/nodenetworkconfig/api/v1alpha"
1111
)
1212

13+
type fakeNodeNetworkConfigUpdater struct {
14+
nnc *v1alpha.NodeNetworkConfig
15+
}
16+
17+
func (f *fakeNodeNetworkConfigUpdater) UpdateSpec(ctx context.Context, spec *v1alpha.NodeNetworkConfigSpec) (*v1alpha.NodeNetworkConfig, error) {
18+
f.nnc.Spec = *spec
19+
return f.nnc, nil
20+
}
21+
1322
func initFakes(t *testing.T,
1423
batchSize,
1524
initialIPConfigCount,
@@ -29,7 +38,7 @@ func initFakes(t *testing.T,
2938
fakecns := fakes.NewHTTPServiceFake()
3039
fakerc := fakes.NewRequestControllerFake(fakecns, scalarUnits, subnetaddresspace, initialIPConfigCount)
3140

32-
poolmonitor := NewCNSIPAMPoolMonitor(fakecns, fakerc)
41+
poolmonitor := NewCNSIPAMPoolMonitor(fakecns, &fakeNodeNetworkConfigUpdater{fakerc.NNC})
3342

3443
fakecns.PoolMonitor = poolmonitor
3544

cns/restserver/internalapi.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -302,9 +302,7 @@ func (service *HTTPRestService) DeleteNetworkContainerInternal(
302302
}
303303

304304
// This API will be called by CNS RequestController on CRD update.
305-
func (service *HTTPRestService) CreateOrUpdateNetworkContainerInternal(
306-
req *cns.CreateNetworkContainerRequest,
307-
) types.ResponseCode {
305+
func (service *HTTPRestService) CreateOrUpdateNetworkContainerInternal(req *cns.CreateNetworkContainerRequest) types.ResponseCode {
308306
if req.NetworkContainerid == "" {
309307
logger.Errorf("[Azure CNS] Error. NetworkContainerid is empty")
310308
return types.NetworkContainerNotSpecified

0 commit comments

Comments
 (0)