Skip to content

Commit 8ae7b8a

Browse files
authored
[NPM] 🐞 {fix} error creating IPsets when same string for ports and labels is used (#734)
* Adding port_ format for named ports * Cleaning existing ipsets incase of a upgrade * Changing the delimiter for port prefix * Some basic formatting * Adding fixes to testcases * Addressing comments * Adding mitigation for empty string in named port * Changing port nil behavior. NPM does partial rule handling in port nil case * removing exists check, as setmap is not accessible from this test * Adding support to delete only azure-npm ipsets * Adding support to delete only azure-npm ipsets * Addressing comments * Changing azure-npm to const flag and cleaning up un wanted error log * Changing the make entries to 0
1 parent a22a852 commit 8ae7b8a

File tree

8 files changed

+209
-47
lines changed

8 files changed

+209
-47
lines changed

npm/ipsm/ipsm.go

Lines changed: 77 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package ipsm
66
import (
77
"os"
88
"os/exec"
9+
"regexp"
910
"strings"
1011
"syscall"
1112

@@ -70,12 +71,12 @@ func (ipsMgr *IpsetManager) Exists(key string, val string, kind string) bool {
7071

7172
// SetExists checks whehter an ipset exists.
7273
func (ipsMgr *IpsetManager) SetExists(setName, kind string) bool {
73-
m := ipsMgr.setMap
74-
if kind == util.IpsetSetListFlag {
75-
m = ipsMgr.listMap
76-
}
77-
_, exists := m[setName]
78-
return exists
74+
m := ipsMgr.setMap
75+
if kind == util.IpsetSetListFlag {
76+
m = ipsMgr.listMap
77+
}
78+
_, exists := m[setName]
79+
return exists
7980
}
8081

8182
func isNsSet(setName string) bool {
@@ -459,4 +460,73 @@ func (ipsMgr *IpsetManager) Restore(configFile string) error {
459460
//TODO based on the set name and number of entries in the config file, update IPSetInventory
460461

461462
return nil
462-
}
463+
}
464+
465+
// DestroyNpmIpsets destroys only ipsets created by NPM
466+
func (ipsMgr *IpsetManager) DestroyNpmIpsets() error {
467+
468+
cmdName := util.Ipset
469+
cmdArgs := util.IPsetCheckListFlag
470+
471+
reply, err := exec.Command(cmdName, cmdArgs).Output()
472+
if msg, failed := err.(*exec.ExitError); failed {
473+
errCode := msg.Sys().(syscall.WaitStatus).ExitStatus()
474+
if errCode > 0 {
475+
metrics.SendErrorMetric(util.IpsmID, "{DestroyNpmIpsets} Error: There was an error running command: [%s] Stderr: [%v, %s]", cmdName, err, strings.TrimSuffix(string(msg.Stderr), "\n"))
476+
}
477+
478+
return err
479+
}
480+
if reply == nil {
481+
metrics.SendErrorMetric(util.IpsmID, "{DestroyNpmIpsets} Received empty string from ipset list while destroying azure-npm ipsets")
482+
return nil
483+
}
484+
485+
log.Logf("{DestroyNpmIpsets} Reply from command %s executed is %s", cmdName+" "+cmdArgs, reply)
486+
re := regexp.MustCompile("Name: (" + util.AzureNpmPrefix + "\\d+)")
487+
ipsetRegexSlice := re.FindAllSubmatch(reply, -1)
488+
489+
if len(ipsetRegexSlice) == 0 {
490+
log.Logf("No Azure-NPM IPsets are found in the Node.")
491+
return nil
492+
}
493+
494+
ipsetLists := make([]string, 0)
495+
for _, matchedItem := range ipsetRegexSlice {
496+
if len(matchedItem) == 2 {
497+
itemString := string(matchedItem[1])
498+
if strings.Contains(itemString, util.AzureNpmFlag) {
499+
ipsetLists = append(ipsetLists, itemString)
500+
}
501+
}
502+
}
503+
504+
if len(ipsetLists) == 0 {
505+
return nil
506+
}
507+
508+
entry := &ipsEntry{
509+
operationFlag: util.IpsetFlushFlag,
510+
}
511+
512+
for _, ipsetName := range ipsetLists {
513+
entry := &ipsEntry{
514+
operationFlag: util.IpsetFlushFlag,
515+
set: ipsetName,
516+
}
517+
518+
if _, err := ipsMgr.Run(entry); err != nil {
519+
metrics.SendErrorMetric(util.IpsmID, "{DestroyNpmIpsets} Error: failed to flush ipset %s", ipsetName)
520+
}
521+
}
522+
523+
for _, ipsetName := range ipsetLists {
524+
entry.operationFlag = util.IpsetDestroyFlag
525+
entry.set = ipsetName
526+
if _, err := ipsMgr.Run(entry); err != nil {
527+
metrics.SendErrorMetric(util.IpsmID, "{DestroyNpmIpsets} Error: failed to destroy ipset %s", ipsetName)
528+
}
529+
}
530+
531+
return nil
532+
}

npm/ipsm/ipsm_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -521,6 +521,28 @@ func TestRun(t *testing.T) {
521521
}
522522
}
523523

524+
func TestDestroyNpmIpsets(t *testing.T) {
525+
ipsMgr := NewIpsetManager()
526+
527+
err := ipsMgr.CreateSet("azure-npm-123456", []string{"nethash"})
528+
if err != nil {
529+
t.Errorf("TestDestroyNpmIpsets failed @ ipsMgr.CreateSet")
530+
t.Errorf(err.Error())
531+
}
532+
533+
err = ipsMgr.CreateSet("azure-npm-56543", []string{"nethash"})
534+
if err != nil {
535+
t.Errorf("TestDestroyNpmIpsets failed @ ipsMgr.CreateSet")
536+
t.Errorf(err.Error())
537+
}
538+
539+
err = ipsMgr.DestroyNpmIpsets()
540+
if err != nil {
541+
t.Errorf("TestDestroyNpmIpsets failed @ ipsMgr.DestroyNpmIpsets")
542+
t.Errorf(err.Error())
543+
}
544+
}
545+
524546
func TestMain(m *testing.M) {
525547
metrics.InitializeAll()
526548
ipsMgr := NewIpsetManager()

npm/npm.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111

1212
"github.com/Azure/azure-container-networking/aitelemetry"
1313
"github.com/Azure/azure-container-networking/log"
14+
"github.com/Azure/azure-container-networking/npm/ipsm"
1415
"github.com/Azure/azure-container-networking/npm/iptm"
1516
"github.com/Azure/azure-container-networking/npm/metrics"
1617
"github.com/Azure/azure-container-networking/npm/util"
@@ -188,6 +189,9 @@ func NewNetworkPolicyManager(clientset *kubernetes.Clientset, informerFactory in
188189
iptMgr := iptm.NewIptablesManager()
189190
iptMgr.UninitNpmChains()
190191

192+
log.Logf("Azure-NPM creating, cleaning existing Azure NPM IPSets")
193+
ipsm.NewIpsetManager().DestroyNpmIpsets()
194+
191195
var (
192196
podInformer = informerFactory.Core().V1().Pods()
193197
nsInformer = informerFactory.Core().V1().Namespaces()

npm/pod.go

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,14 @@ func (npMgr *NetworkPolicyManager) AddPod(podObj *corev1.Pod) error {
9292
case v1.ProtocolSCTP:
9393
protocol = util.IpsetSCTPFlag
9494
}
95-
ipsMgr.AddToSet(port.Name, fmt.Sprintf("%s,%s%d", podIP, protocol, port.ContainerPort), util.IpsetIPPortHashFlag, podUid)
95+
namedPortname := util.NamedPortIPSetPrefix + port.Name
96+
ipsMgr.AddToSet(
97+
namedPortname,
98+
fmt.Sprintf("%s,%s%d", podIP, protocol, port.ContainerPort),
99+
util.IpsetIPPortHashFlag,
100+
podUid,
101+
)
102+
96103
}
97104
}
98105
}
@@ -209,7 +216,12 @@ func (npMgr *NetworkPolicyManager) DeletePod(podObj *corev1.Pod) error {
209216
case v1.ProtocolSCTP:
210217
protocol = util.IpsetSCTPFlag
211218
}
212-
ipsMgr.DeleteFromSet(port.Name, fmt.Sprintf("%s,%s%d", cachedPodIp, protocol, port.ContainerPort), podUid)
219+
namedPortname := util.NamedPortIPSetPrefix + port.Name
220+
ipsMgr.DeleteFromSet(
221+
namedPortname,
222+
fmt.Sprintf("%s,%s%d", cachedPodIp, protocol, port.ContainerPort),
223+
podUid,
224+
)
213225
}
214226
}
215227
}

npm/pod_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,18 @@ func TestAddPod(t *testing.T) {
7070
Phase: "Running",
7171
PodIP: "1.2.3.4",
7272
},
73+
Spec: corev1.PodSpec{
74+
Containers: []corev1.Container{
75+
corev1.Container{
76+
Ports: []corev1.ContainerPort{
77+
corev1.ContainerPort{
78+
Name: "app:test-pod",
79+
ContainerPort: 8080,
80+
},
81+
},
82+
},
83+
},
84+
},
7385
}
7486

7587
npMgr.Lock()

0 commit comments

Comments
 (0)