Skip to content

Commit 469afea

Browse files
authored
test: add ut for populating network and endpoint hns id in endpoint and endpoint info structs (#2844)
* validate endpoint struct after endpoint creation * add uts to validate endpoint info and endpoint structs have hns network and endpoint id fields populated endpoint struct should have the hns endpoint id after new endpoint endpoint info struct should have the hns endpoint id after new endpoint as well network struct should have the hns network id after new network endpoint info struct should have the hns network id after new network as well endpoint struct should have the hns network id after new endpoint if endpoint info had it * address linter issue * address feedback by validating info sent to cns * modify hnsv2 wrapper behavior to only set hns id if not already set for npm uts
1 parent 171c75b commit 469afea

File tree

9 files changed

+201
-13
lines changed

9 files changed

+201
-13
lines changed

network/endpoint.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/Azure/azure-container-networking/netlink"
1616
"github.com/Azure/azure-container-networking/network/policy"
1717
"github.com/Azure/azure-container-networking/platform"
18+
"github.com/pkg/errors"
1819
"go.uber.org/zap"
1920
)
2021

@@ -386,3 +387,25 @@ func (epInfo *EndpointInfo) IsEndpointStateIncomplete() bool {
386387
}
387388
return false
388389
}
390+
391+
func (ep *endpoint) validateEndpoint() error {
392+
if ep.ContainerID == "" || ep.NICType == "" {
393+
return errors.New("endpoint struct must contain a container id and nic type")
394+
}
395+
return nil
396+
}
397+
398+
func validateEndpoints(eps []*endpoint) error {
399+
containerIDs := map[string]bool{}
400+
for _, ep := range eps {
401+
if err := ep.validateEndpoint(); err != nil {
402+
return errors.Wrap(err, "failed to validate endpoint struct")
403+
}
404+
containerIDs[ep.ContainerID] = true
405+
406+
if len(containerIDs) != 1 {
407+
return errors.New("multiple distinct container ids detected")
408+
}
409+
}
410+
return nil
411+
}

network/endpoint_test.go

Lines changed: 81 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -175,10 +175,11 @@ var _ = Describe("Test Endpoint", func() {
175175
Endpoints: map[string]*endpoint{},
176176
}
177177
epInfo := &EndpointInfo{
178-
EndpointID: "768e8deb-eth1",
179-
Data: make(map[string]interface{}),
180-
IfName: eth0IfName,
181-
NICType: cns.InfraNIC,
178+
EndpointID: "768e8deb-eth1",
179+
Data: make(map[string]interface{}),
180+
IfName: eth0IfName,
181+
NICType: cns.InfraNIC,
182+
ContainerID: "0ea7476f26d192f067abdc8b3df43ce3cdbe324386e1c010cb48de87eefef480",
182183
}
183184
epInfo.Data[VlanIDKey] = 100
184185

@@ -206,6 +207,7 @@ var _ = Describe("Test Endpoint", func() {
206207
Expect(ep.Gateways[0].String()).To(Equal("192.168.0.1"))
207208
Expect(ep.VlanID).To(Equal(epInfo.Data[VlanIDKey].(int)))
208209
Expect(ep.IfName).To(Equal(epInfo.IfName))
210+
Expect(ep.ContainerID).To(Equal(epInfo.ContainerID))
209211
})
210212
It("Should be not added", func() {
211213
// Adding an endpoint with an id.
@@ -374,4 +376,79 @@ var _ = Describe("Test Endpoint", func() {
374376
})
375377
})
376378
})
379+
380+
// validation when calling add
381+
Describe("Test validateEndpoints", func() {
382+
Context("When in a single add call we create two endpoint structs", func() {
383+
It("Should have the same container id", func() {
384+
eps := []*endpoint{
385+
{
386+
ContainerID: "0ea7476f26d192f067abdc8b3df43ce3cdbe324386e1c010cb48de87eefef480",
387+
NICType: cns.InfraNIC,
388+
},
389+
{
390+
ContainerID: "0ea7476f26d192f067abdc8b3df43ce3cdbe324386e1c010cb48de87eefef480",
391+
NICType: cns.DelegatedVMNIC,
392+
},
393+
}
394+
Expect(validateEndpoints(eps)).To(BeNil())
395+
})
396+
})
397+
Context("When in a single add call we have different container ids", func() {
398+
It("Should error", func() {
399+
eps := []*endpoint{
400+
{
401+
ContainerID: "0ea7476f26d192f067abdc8b3df43ce3cdbe324386e1c010cb48de87eefef480",
402+
NICType: cns.InfraNIC,
403+
},
404+
{
405+
ContainerID: "0ea7476f26d192f067abdc8b3df43ce3cdbe324386e1c010cb48de87eefef481",
406+
NICType: cns.DelegatedVMNIC,
407+
},
408+
}
409+
Expect(validateEndpoints(eps)).ToNot(BeNil())
410+
})
411+
})
412+
Context("When no container id", func() {
413+
It("Should error", func() {
414+
eps := []*endpoint{
415+
{
416+
ContainerID: "",
417+
NICType: cns.InfraNIC,
418+
},
419+
{
420+
ContainerID: "",
421+
NICType: cns.DelegatedVMNIC,
422+
},
423+
}
424+
Expect(validateEndpoints(eps)).ToNot(BeNil())
425+
})
426+
})
427+
Context("When missing nic type", func() {
428+
It("Should error", func() {
429+
eps := []*endpoint{
430+
{
431+
ContainerID: "0ea7476f26d192f067abdc8b3df43ce3cdbe324386e1c010cb48de87eefef480",
432+
NICType: cns.InfraNIC,
433+
},
434+
{
435+
ContainerID: "0ea7476f26d192f067abdc8b3df43ce3cdbe324386e1c010cb48de87eefef480",
436+
NICType: "",
437+
},
438+
}
439+
Expect(validateEndpoints(eps)).ToNot(BeNil())
440+
})
441+
})
442+
Context("When no container id ib nic", func() {
443+
It("Should error", func() {
444+
eps := []*endpoint{
445+
{
446+
ContainerID: "",
447+
NICType: cns.NodeNetworkInterfaceBackendNIC,
448+
},
449+
}
450+
Expect(validateEndpoints(eps)).ToNot(BeNil())
451+
})
452+
})
453+
})
377454
})

network/endpoint_windows_test.go

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,7 @@ func TestNewAndDeleteEndpointImplHnsV2(t *testing.T) {
3535

3636
// this hnsv2 variable overwrites the package level variable in network
3737
// we do this to avoid passing around os specific objects in platform agnostic code
38-
Hnsv2 = hnswrapper.Hnsv2wrapperwithtimeout{
39-
Hnsv2: hnswrapper.NewHnsv2wrapperFake(),
40-
}
38+
Hnsv2 = hnswrapper.NewHnsv2wrapperFake()
4139

4240
epInfo := &EndpointInfo{
4341
EndpointID: "753d3fb6-e9b3-49e2-a109-2acc5dda61f1",
@@ -50,15 +48,35 @@ func TestNewAndDeleteEndpointImplHnsV2(t *testing.T) {
5048
Servers: []string{"10.0.0.1, 10.0.0.2"},
5149
Options: nil,
5250
},
53-
MacAddress: net.HardwareAddr("00:00:5e:00:53:01"),
51+
MacAddress: net.HardwareAddr("00:00:5e:00:53:01"),
52+
NICType: cns.InfraNIC,
53+
HNSNetworkID: "853d3fb6-e9b3-49e2-a109-2acc5dda61f1",
5454
}
55-
endpoint, err := nw.newEndpointImplHnsV2(nil, epInfo)
55+
ep, err := nw.newEndpointImplHnsV2(nil, epInfo)
5656
if err != nil {
5757
fmt.Printf("+%v", err)
5858
t.Fatal(err)
5959
}
6060

61-
err = nw.deleteEndpointImplHnsV2(endpoint)
61+
if err = validateEndpoints([]*endpoint{ep}); err != nil {
62+
fmt.Printf("+%v", err)
63+
t.Fatal(err)
64+
}
65+
66+
if epInfo.HNSEndpointID == "" {
67+
t.Fatal("hns endpoint id not populated inside endpoint info during new endpoint impl call")
68+
}
69+
70+
if ep.HnsId == "" {
71+
t.Fatal("hns endpoint id not populated inside endpoint struct during new endpoint impl call")
72+
}
73+
74+
if ep.HNSNetworkID == "" {
75+
t.Fatal("hns network id was not copied to the endpoint struct during new endpoint impl call")
76+
}
77+
78+
err = nw.deleteEndpointImplHnsV2(ep)
79+
6280
if err != nil {
6381
fmt.Printf("+%v", err)
6482
t.Fatal(err)

network/hnswrapper/hnsv2wrapperfake.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,9 @@ func (f Hnsv2wrapperFake) CreateNetwork(network *hcn.HostComputeNetwork) (*hcn.H
5050
defer f.Unlock()
5151

5252
delayHnsCall(f.Delay)
53+
if network.Id == "" {
54+
network.Id = network.Name // simulate hns creating the network and generating an hns network id
55+
}
5356
f.Cache.networks[network.Name] = NewFakeHostComputeNetwork(network)
5457
return network, nil
5558
}
@@ -216,6 +219,9 @@ func (f Hnsv2wrapperFake) CreateEndpoint(endpoint *hcn.HostComputeEndpoint) (*hc
216219
f.Lock()
217220
defer f.Unlock()
218221
delayHnsCall(f.Delay)
222+
if endpoint.Id == "" {
223+
endpoint.Id = endpoint.Name // simulate hns creating the endpoint and generating an hns endpoint id
224+
}
219225
f.Cache.endpoints[endpoint.Id] = NewFakeHostComputeEndpoint(endpoint)
220226
return endpoint, nil
221227
}

network/manager.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -423,15 +423,30 @@ func (nm *networkManager) UpdateEndpointState(eps []*endpoint) error {
423423
logger.Info("Update endpoint state", zap.String("hnsEndpointID", ipinfo.HnsEndpointID), zap.String("hnsNetworkID", ipinfo.HnsNetworkID),
424424
zap.String("hostVethName", ipinfo.HostVethName), zap.String("macAddress", ipinfo.MacAddress), zap.String("nicType", string(ipinfo.NICType)))
425425
}
426-
// logger.Info("Calling cns updateEndpoint API with ", zap.String("containerID: ", ep.ContainerID), zap.String("HnsId: ", ep.HnsId), zap.String("HostIfName: ", ep.HostIfName))
426+
427427
// we assume all endpoints have the same container id
428-
response, err := nm.CnsClient.UpdateEndpoint(context.TODO(), eps[0].ContainerID, ifnameToIPInfoMap)
428+
cnsEndpointID := eps[0].ContainerID
429+
if err := validateUpdateEndpointState(cnsEndpointID, ifnameToIPInfoMap); err != nil {
430+
return errors.Wrap(err, "failed to validate update endpoint state that will be sent to cns")
431+
}
432+
response, err := nm.CnsClient.UpdateEndpoint(context.TODO(), cnsEndpointID, ifnameToIPInfoMap)
429433
if err != nil {
430434
return errors.Wrapf(err, "Update endpoint API returend with error")
431435
}
432436
logger.Info("Update endpoint API returend ", zap.String("podname: ", response.ReturnCode.String()))
433437
return nil
434438
}
439+
func validateUpdateEndpointState(endpointID string, ifNameToIPInfoMap map[string]*restserver.IPInfo) error {
440+
if endpointID == "" {
441+
return errors.New("endpoint id empty while validating update endpoint state")
442+
}
443+
for ifName := range ifNameToIPInfoMap {
444+
if ifName == "" {
445+
return errors.New("an interface name is empty while validating update endpoint state")
446+
}
447+
}
448+
return nil
449+
}
435450

436451
// GetEndpointState will make a call to CNS GetEndpointState API in the stateless CNI mode to fetch the endpointInfo
437452
// TODO unit tests need to be added, WorkItem: 26606939

network/manager_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,44 @@ var _ = Describe("Test Manager", func() {
229229
Expect(num).To(Equal(3))
230230
})
231231
})
232+
233+
Context("When different fields passed to update endpoint state", func() {
234+
It("Should error or validate correctly", func() {
235+
nm := &networkManager{}
236+
237+
err := nm.UpdateEndpointState([]*endpoint{
238+
{
239+
IfName: "eth0",
240+
ContainerID: "2bfc3b23e078f0bea48612d5d081ace587599cdac026d23e4d57bd03c85d357c",
241+
},
242+
{
243+
IfName: "",
244+
ContainerID: "2bfc3b23e078f0bea48612d5d081ace587599cdac026d23e4d57bd03c85d357c",
245+
},
246+
})
247+
Expect(err).To(HaveOccurred())
248+
249+
err = nm.UpdateEndpointState([]*endpoint{
250+
{
251+
IfName: "eth1",
252+
ContainerID: "",
253+
},
254+
{
255+
IfName: "eth0",
256+
ContainerID: "",
257+
},
258+
})
259+
Expect(err).To(HaveOccurred())
260+
261+
err = validateUpdateEndpointState(
262+
"2bfc3b23e078f0bea48612d5d081ace587599cdac026d23e4d57bd03c85d357c",
263+
map[string]*restserver.IPInfo{
264+
"eth1": {},
265+
"eth2": {},
266+
})
267+
Expect(err).To(BeNil())
268+
})
269+
})
232270
})
233271
Describe("Test EndpointCreate", func() {
234272
Context("When no endpoints provided", func() {

network/network.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -346,6 +346,10 @@ func (nm *networkManager) EndpointCreate(cnsclient apipaClient, epInfos []*Endpo
346346
eps = append(eps, ep)
347347
}
348348

349+
if err := validateEndpoints(eps); err != nil {
350+
return err
351+
}
352+
349353
// save endpoints
350354
return nm.SaveState(eps)
351355
}

network/network_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ var _ = Describe("Test Network", func() {
197197
Mode: opModeTransparentVlan,
198198
}
199199
nw, err := nm.newNetwork(nwInfo)
200-
Expect(err).To(MatchError(platform.ErrMockExec))
200+
Expect(err).NotTo(BeNil())
201201
Expect(nw).To(BeNil())
202202
})
203203
})

network/network_windows_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,13 @@ func TestNewAndDeleteNetworkImplHnsV2(t *testing.T) {
5252
t.Fatal(err)
5353
}
5454

55+
if network.HnsId == "" {
56+
t.Fatal("hns network id not populated in network struct")
57+
}
58+
if nwInfo.HNSNetworkID == "" {
59+
t.Fatal("hns network id not populated")
60+
}
61+
5562
err = nm.deleteNetworkImplHnsV2(network)
5663

5764
if err != nil {

0 commit comments

Comments
 (0)