Skip to content

Commit c39e7f2

Browse files
Copilotthatmattlong
andcommitted
Fix logging response from NMAgent in syncHostNCVersion function
Co-authored-by: thatmattlong <[email protected]>
1 parent f86196e commit c39e7f2

File tree

2 files changed

+116
-2
lines changed

2 files changed

+116
-2
lines changed

cns/restserver/internalapi.go

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,10 +226,18 @@ func (service *HTTPRestService) syncHostNCVersion(ctx context.Context, channelMo
226226
nmaNCs[strings.ToLower(nc.NetworkContainerID)] = nc.Version
227227
}
228228
hasNC.Set(float64(len(nmaNCs)))
229+
230+
// Track NCs missing from NMAgent response and outdated NCs for better error reporting
231+
missingNCs := make(map[string]string) // ncID -> expected version
232+
outdatedNMaNCs := make(map[string]string) // ncID -> "expected:actual" version info
233+
229234
for ncID := range outdatedNCs {
230235
nmaNCVersionStr, ok := nmaNCs[ncID]
231236
if !ok {
232-
// NMA doesn't have this NC that we need programmed yet, bail out
237+
// NMA doesn't have this NC that we need programmed yet, track as missing
238+
if ncInfo, exists := service.state.ContainerStatus[ncID]; exists {
239+
missingNCs[ncID] = ncInfo.CreateNetworkContainerRequest.Version
240+
}
233241
continue
234242
}
235243
nmaNCVersion, err := strconv.Atoi(nmaNCVersionStr)
@@ -258,6 +266,20 @@ func (service *HTTPRestService) syncHostNCVersion(ctx context.Context, channelMo
258266
logger.Errorf("NC version from NMA is decreasing: have %d, got %d", localNCVersion, nmaNCVersion)
259267
continue
260268
}
269+
270+
expectedVersion := ncInfo.CreateNetworkContainerRequest.Version
271+
expectedVersionInt, err := strconv.Atoi(expectedVersion)
272+
if err != nil {
273+
logger.Errorf("failed to parse expected NC version string %s: %s", expectedVersion, err)
274+
continue
275+
}
276+
277+
// Check if NMAgent version is still outdated compared to expected DNC version
278+
if nmaNCVersion < expectedVersionInt {
279+
outdatedNMaNCs[ncID] = fmt.Sprintf("expected:%s,actual:%s", expectedVersion, nmaNCVersionStr)
280+
continue
281+
}
282+
261283
if channelMode == cns.CRD {
262284
service.MarkIpsAsAvailableUntransacted(ncInfo.ID, nmaNCVersion)
263285
}
@@ -271,7 +293,18 @@ func (service *HTTPRestService) syncHostNCVersion(ctx context.Context, channelMo
271293
// if we didn't empty out the needs update set, NMA has not programmed all the NCs we are expecting, and we
272294
// need to return an error indicating that
273295
if len(outdatedNCs) > 0 {
274-
return len(programmedNCs), errors.Errorf("unabled to update some NCs: %v, missing or bad response from NMA", outdatedNCs)
296+
var errorParts []string
297+
if len(missingNCs) > 0 {
298+
errorParts = append(errorParts, fmt.Sprintf("missing NCs from NMAgent response: %v", missingNCs))
299+
}
300+
if len(outdatedNMaNCs) > 0 {
301+
errorParts = append(errorParts, fmt.Sprintf("outdated NCs in NMAgent response: %v", outdatedNMaNCs))
302+
}
303+
if len(errorParts) == 0 {
304+
// Fallback for any unexpected cases
305+
errorParts = append(errorParts, fmt.Sprintf("unable to update NCs: %v", outdatedNCs))
306+
}
307+
return len(programmedNCs), errors.Errorf("unable to update some NCs - %s", strings.Join(errorParts, "; "))
275308
}
276309

277310
return len(programmedNCs), nil

cns/restserver/internalapi_test.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"os"
1212
"reflect"
1313
"strconv"
14+
"strings"
1415
"sync"
1516
"testing"
1617
"time"
@@ -330,6 +331,86 @@ func createNCReqeustForSyncHostNCVersion(t *testing.T) cns.CreateNetworkContaine
330331
return req
331332
}
332333

334+
func TestSyncHostNCVersionErrorMessages(t *testing.T) {
335+
tests := []struct {
336+
name string
337+
ncVersionInDNC string
338+
nmaResponse nma.NCVersionList
339+
expectedErrorSubstring string
340+
}{
341+
{
342+
name: "missing NC from NMAgent response",
343+
ncVersionInDNC: "2",
344+
nmaResponse: nma.NCVersionList{
345+
Containers: []nma.NCVersion{}, // Empty response - NC is missing
346+
},
347+
expectedErrorSubstring: "missing NCs from NMAgent response",
348+
},
349+
{
350+
name: "outdated NC in NMAgent response",
351+
ncVersionInDNC: "2",
352+
nmaResponse: nma.NCVersionList{
353+
Containers: []nma.NCVersion{
354+
{
355+
NetworkContainerID: ncID,
356+
Version: "1", // Outdated version compared to DNC version 2
357+
},
358+
},
359+
},
360+
expectedErrorSubstring: "outdated NCs in NMAgent response",
361+
},
362+
}
363+
364+
for _, tt := range tests {
365+
t.Run(tt.name, func(t *testing.T) {
366+
// Create NC request with specified DNC version
367+
restartService()
368+
setEnv(t)
369+
setOrchestratorTypeInternal(cns.KubernetesCRD)
370+
371+
secondaryIPConfigs := make(map[string]cns.SecondaryIPConfig)
372+
ipAddress := "10.0.0.16"
373+
secIPConfig := newSecondaryIPConfig(ipAddress, 0)
374+
ipID := uuid.New()
375+
secondaryIPConfigs[ipID.String()] = secIPConfig
376+
_ = createNCReqInternal(t, secondaryIPConfigs, ncID, tt.ncVersionInDNC)
377+
378+
// Set up mock NMAgent with the specified response
379+
mnma := &fakes.NMAgentClientFake{
380+
GetNCVersionListF: func(_ context.Context) (nma.NCVersionList, error) {
381+
return tt.nmaResponse, nil
382+
},
383+
}
384+
cleanup := setMockNMAgent(svc, mnma)
385+
defer cleanup()
386+
387+
// Call syncHostNCVersion and verify it returns the expected error
388+
programmedCount, err := svc.syncHostNCVersion(context.Background(), cns.KubernetesCRD)
389+
390+
t.Logf("Test case: %s, programmedCount: %d, error: %v", tt.name, programmedCount, err)
391+
392+
if err == nil {
393+
t.Errorf("Expected error but got none")
394+
return
395+
}
396+
397+
if !strings.Contains(err.Error(), tt.expectedErrorSubstring) {
398+
t.Errorf("Expected error message to contain '%s', but got: %s", tt.expectedErrorSubstring, err.Error())
399+
}
400+
401+
// In the outdated case, NMAgent has a version of the NC so it counts as programmed, just not up-to-date
402+
expectedProgrammedCount := 0
403+
if tt.name == "outdated NC in NMAgent response" {
404+
expectedProgrammedCount = 1 // NMAgent has version 1, so it's programmed to some version
405+
}
406+
407+
if programmedCount != expectedProgrammedCount {
408+
t.Errorf("Expected programmedCount to be %d, but got %d", expectedProgrammedCount, programmedCount)
409+
}
410+
})
411+
}
412+
}
413+
333414
func TestReconcileNCWithEmptyState(t *testing.T) {
334415
restartService()
335416
setEnv(t)

0 commit comments

Comments
 (0)